Spring事务的传播性及隔离级别

James 2019年11月14日 70次浏览

什么是事务?

保证业务(一系列对数据库增删改操作)的原子性,原子:表示不可分割,要么存在要么不存在,是一个最小单位。那么事务就是一批操作视为一个原子操作,要么成功要么失败。

事务的ACID特性

  • A(Atomic):原子性,当前事务操作是一个最小单位,不可拆分。
  • C(Consistency):一致性,不论事务执行成功还是失败,数据库中的数据始终是一致的。
  • I(Isolation):隔离性,多个事务操作同一笔数据时,各个事务处于一个被隔离的空间,是独立的。
  • D(Durability):持久性,一旦事务提交,修改的数据是永久性的。

事务的隔离级别

  • 脏读:一个事务读到另一个事务未提交的更新数据,而另一个事务最终回滚,我们称这类数据为脏数据,这种现象称为脏读。
  • 不可重复读:事务T1多次读取同一数据,而事务多T2次对这一数据进行更新,导致T1每次读取的数据不一样。
  • 幻读:事务T1执行一次查询,然后事务T2插入或者删除一条数据,恰好T2这条操作的数据刚好满足T1的检索条件。这时事务T1再执行一次查询,此时得到的数据和第一次查询的数据不一致,这种现象称为幻读。
    数据库事务隔离级别(4种),Spring除了有数据库的4种还有一种默认。
  • ISOLATION_DEFAULT:默认使用数据库的事务隔离级别。
  • ISOLATION_READ_UNCOMMITTED:读未提交,可以读到未提交的数据,该级别可能会出现脏读、不可重复读、幻读等问题。
  • ISOLATION_READ_COMMITTED:读已提交,只能读到已提交的数据,该级别可以有效避免脏读,但可能会出现不可重复读、幻读的问题。Oracle,SQL Server默认使用此级别。
  • ISOLATION_REPEATABLE_READ:可重复读,该方式专门为不可重复读这一现象定制,改级别可以避免脏读和不可重复读,但可能会出现幻读。MySQL默认使用此级别。
  • ISOLATION_SERIALIZABLE:可串行化,将事务按照顺序执行,即多个事务不能同时执行,该级别为最高级别,性能上有较大影响,但能避免脏读、不可重复读、幻读等问题。

注意:如果想在某个业务方法中可以读取到未提交的数据,可以使用@Transactional(isolation = Isolation.READ_UNCOMMITTED)来设置事务的隔离级别。

Spring事务的传播性

事务的传播特性的产生,当多个业务嵌套调用时事务的执行策略,是Spring利用其底层资源特性来实现的。
Spring为我们提供了以下其中事务的传播性

  1. PROPAGATION_REQUIRED:必须使用事务,如果当前业务存在一个事务,则加入,如果不存在,则创建一个事务,默认使用此种方式。
  2. PROPAGATION_SUPPORTS:支持事务,如果父业务存在事务,则加入,如果不存在,则不使用事务。
  3. PROPAGATION_MANDATORY:强制使用事务,如果父业务不存在事务,则抛出异常。
  4. PROPAGATION_REQUIRES_NEW:如果当前存在事务,则挂起该事务新建一个事务,如果不存在事务,则同PROPAGATION_REQUIRED
  5. PROPAGATION_NOT_SUPPORTED:不支持事务,如果当前存在事务,则挂起,自己不使用事务去执行数据库操作。
  6. PROPAGATION_NEVER:不使用事务,如果当前存在事务,则抛出异常。
  7. PROPAGATION_NESTED:嵌套事务,如果当前存在事务,则开启一个子事务,但是父事务可以控制子事务是否提交和回滚,子事务的回滚父事务可以选择回滚或者提交。如果当前不存在事务,则同PROPAGATION_REQUIRED