传播行为:
PROPAGATION_REQUIRED:支持现在的事务,如果没有就创建一个 默认事务级别
PROPAGATION_MANDATORY:必须在一个现存的事务中,否则就抛异常
PROPAGATION_NEST:在一个嵌入的事务中进行,如果不是,则同PROPAGATION_REQUIRED
PROPAGATION_NEVER:不应当在事务中进行,如果有就抛出异常
PROPAGATION_NOT_SUPPORTED:不应当在事务中进行,如果有就暂停当前的事务
PROPAGATION_REQUIRES_NEW:建立一个新的事务,如果现存一个事务就暂停它
PROPAGATION_SUPPORTS:支持现在的事务,如果没有,就以非事务的方式执行。
隔离级别:
DEFAULT | 使用数据库默认的事务隔离级别 | |
READ_UNCOMMITTED | 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。 | |
READ_COMMITTED | 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。 | |
REPEATABLE_READ | 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。 | |
SERIALIZABLE |
|
影响:
脏读 | 不可重复读 | 幻读 | |
READ_UNCOMMITTED | √ | √ | √ |
READ_COMMITTED | × | √ | √ |
REPEATABLE_READ | × | × | √ |
SERIALIZABLE | × | × | × |
事务管理器:
大多数项目只需要一个事务管理器。然而,有些项目为了提高效率、或者有多个完全不同又不相干的数据源,最好用多个事务管理器。机智的Spring的Transactional管理已经考虑到了这一点,首先分别定义多个transactional manager,并为qualifier属性指定不同的值;然后在需要使用@Transactional注解的时候指定TransactionManager的qualifier属性值或者直接使用bean名称
<bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource1"></property>
<qualifier value="datasource1Tx"/>
</bean>
<bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource2"></property>
<qualifier value="datasource2Tx"/>
</bean>
用@Transactional("datasource1Tx")和@Transactional("datasource2Tx"),来区别具体使用某个事务管理器
或者,直接使用transactin manager 的bean名字:@Transactional("transactionManager1")
如果是使用@Transactional(),相当于使用缺省的transaction mananger名字,即:@Transactional("transactionManager")
就我这么多年接触的平时喜欢使用@Transactional来做事务的开发同学而言,绝大多数都不清楚事务的5种隔离级别与7种传播属性他们是如何相互影响的。
另外,在传统的单系统的业务中,因为所有的表都在同一个库中,而且基本没有RPC、HTTP调用,所以使用声明式事务很多时候不会有问题,但是在SOA架构中,则绝大多数场景都会有问题。
https://pan.baidu.com/s/1zdvZucsF9VJU97wKr-UIGg#list/path=%2F