@Transaction的重要属性
Propagation
主要用来配置当前需要执行的方法,与之前是否有transaction(事务)之间的关系,用于规定事物的传播行为.
REQUIRED(默认值):在有transaction状态下执行;如当前没有transaction,则创建新的transaction;
SUPPORTS:如当前有transaction,则在transaction状态下执行;如果当前没有transaction,在无transaction状态下执行;
MANDATORY:必须在有transaction状态下执行,如果当前没有transaction,则抛出异常IllegalTransactionStateException;
REQUIRES_NEW:创建新的transaction并执行;如果当前已有transaction,则将当前transaction挂起;
NOT_SUPPORTED:在无transaction状态下执行;如果当前已有transaction,则将当前transaction挂起;
NEVER:在无transaction状态下执行;如果当前已有transaction,则抛出异常IllegalTransactionStateException。
例如常用:
@Transactional(propagation = Propagation.SUPPORTS)
isolation
该属性用于设置底层数据库的事务隔离级别 事务隔离级别介绍:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)
读取已提交数据,存在幻读,会读到其它事务新插入的数据)
@Transactional(isolation = Isolation.REPEATABLE_READ)
可重复读(不会读到其它事务对所查询数据的修改)
@Transactional(isolation = Isolation.SERIALIZABLE)
串行化
什么是脏读、幻读、不可重复读?
脏读
一个事务读取到另一事务未提交的更新数据
不可重复读
在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
幻读
表现:一个事务(同一个read view)在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行。两点需要说明:
1、在可重复读隔离级别下,普通查询是快照读,是不会看到别的事务插入的数据的,幻读只在当前读下才会出现。
2、幻读专指新插入的行,读到原本存在行的更新结果不算(指在读取之前已经更新的值)。
幻读的影响
- 会造成一个事务中先产生的锁,无法锁住后加入的满足条件的行。
- 产生数据一致性问题,在一个事务中,先对符合条件的目标行做变更,而在事务提交前有新的符合目标条件的行加入。这样通过binlog恢复的数据是会将所有符合条件的目标行都进行变更的。
幻读产生的原因
- 行锁只能锁住行,即使把所有的行记录都上锁,也阻止不了新插入的记录。
如何解决幻读
- 将两行记录间的空隙加上锁,阻止新记录的插入;这个锁称为间隙锁。
- 间隙锁与间隙锁之间没有冲突关系。跟间隙锁存在冲突关系的,是往这个间隙中插入一个记录这个操作。 其中MySQL默认使用的隔离级别为REPEATABLE_READ、Oracle的为READ_COMMITTED