这两天整理spring aop和spring事务的东西。顺便把自己对于spring事务的隔离机制的理解整理了下。
问题:
spring事务传播机制都有几种,他们的特性是什么,用不好会不会踩坑。
源码实现为(DataSourceTransactionManager ,AbstractPlatformTransactionManager)最好多看源码有自己的理解。
事务传播性的描述及理解:
1、REQUIRED 默认的,不配就这个。支持当前的事务,如果当前没有事务开启一个事务 传播性
2、SUPPORTS 支持当前事务,如果没有就不开启新事物,也有传播性
3、MANDATORY(强制的) 支持当前事务,如果前面没有开始事务,或抛出异常
4、REQUIRES_NEW 开始新事物,如果已存在事务,则挂起 ,在本方法的没有声明事务的子方法内不传播
5、NOT_SUPPORTED 事务在本方法和没有声明事务的子方法内不传播
6、NEVER 有事务就抛异常 完全不传播
7、PROPAGATION_NESTED – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。
它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager)
最难理解的就是嵌套事务及嵌套事务与开启新事务的区别,下面是例子及通俗理解:
嵌套事务:
PROPAGATION_NESTED 开始一个 “嵌套的” 事务, 它是已经存在事务的一个真正的子事务. 嵌套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交. (提交一起提交,失败自己失败,外部失败自己也跟着失败)
也就是说,PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED区别在于前者是一个全新的事务,而后者则是外部事务的子事务,如果外部事务commit,嵌套事务也commit,外事务回滚他回滚。
特性: 外事务提交,他提交,外事务回滚,他回滚,但是他失败外事务不回滚,因为他是外事务的子事务,他有自己的隔离和锁,
PROPAGATION_REQUIRES_NEW 是自己开启一个事务,自己提交自己的,自己回滚自己的。互相隔离
PROPAGATION_NESTED 也是开一个事务,但是这个事务依赖于外面的事务,外面的事务提交,他才能提交,外面的回滚他才能回滚,他是外事务的事务的一部分,自己失败不影响外面。隔离级别较低
如果要是用异常,通知到外面异常,外面仍然回滚。
示例:
requries_new:
@Required
method A {
B();//配置NESTED
C();
}
A已经开启事务(transaction_a),如果配置的为嵌套的事务,如果b方法开启事务(transaction_b)开启并执行成功(其实还没有commit,到底是否commit或者callback由transaction_a的执行情况决定–这也是他的核心区别),但是C()如果发生异常,导致transaction_a发生回滚,此时transaction_b也会回滚到自己的savepoint;
@Required
method A {
B();//配置了Required_new
C();
}
A已经开启事务(transaction_a),如果配置的为使用新的事务,如果b方法进入此时transaction_a已挂起,这时开启事务(transaction_b)开启并执行成功,但是C()如果发生异常,导致transaction_a发生回滚,此时transaction_b不会回滚到自己的savepoint,因为transaction_b已经在方法b()执行完毕的时候已经提交了;