Spring 事务注解 @Transaction

173 阅读3分钟

@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