Spring 七种事务传播机制和五种事务隔离级别

一、Propagation (事务的传播属性)

propagation 属性确定代理应该给哪个方法增加事务行为,这样的属性最重要的部份是传播行为,有以下选项可供使用:

  • PROPAGATION_REQUIRED —— 支持当前事务,如果当前没有事务,则新建一个事务,这是最常见的选择,也是 Spring 默认的一个事务传播属性。

  • PROPAGATION_SUPPORTS —— 支持当前事务,如果当前没有事务,则以非事务方式执行。

  • PROPAGATION_MANDATORY —— 支持当前事务,如果当前没有事务,则抛出异常。

  • PROPAGATION_REQUIRES_NEW —— 新建事务,如果当前存在事务,把当前事务挂起。

  • PROPAGATION_NOT_SUPPORTED —— 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

  • PROPAGATION_NEVER —— 以非事务方式执行,如果当前存在事务,则抛出异常。

1、PROPAGATION_REQUIRED

注解用法如:@Transactional (propagation = Propagation.REQUIRED )

默认的spring事务传播级别,使用该级别的特点是,如果上下文中已经存在事务,那么就加入到事务中执行,如果当前上下文中不存在事务,则新建事务执行。所以这个级别通常能满足处理大多数的业务场景。

比如,ServiceB.methodB的事务级别定义为 PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候,ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA
的事务内部,就不再起新的事务;

而假如ServiceA.methodA运行的时候发现自己没有在事务中,它就会为自己分配一个事务。这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚。

2、PROPAGATION_SUPPORTS

该传播级别的特点是,如果上下文存在事务,则支持事务加入事务,如果没有事务,则使用非事务的方式执行。所以说,并非所有的包在transactionTemplate.execute中的代码都会有事务支持。这个通常是用来处理那些并非原子性的非核心业务逻辑操作。

应用场景较少。

3、PROPAGATION_MANDATORY

该级别的事务要求上下文中必须要存在事务,否则就会抛出异常!

配置该方式的传播级别是有效的控制上下文调用代码遗漏添加事务控制的保证手段。

比如一段代码不能单独被调用执行,但是一旦被调用,就必须有事务包含的情况,就可以使用这个传播级别。

4、PROPAGATION_REQUIRES_NEW

该传播级别的特点是,每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。

比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,
那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,
它才继续执行。它与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在
两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,
如果它抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。

5、PROPAGATION_NOT_SUPPORTED

该传播属性不支持事务,该级别的特点就是上下文中存在事务,则挂起事务,执行当前逻辑,结束后恢复上下文的事务。

这个级别有什么好处?可以帮助你将事务极可能的缩小。因为一个事务越大,它存在的风险也就越多。所以在处理事务的过程中,要保证尽可能的缩小范围。

比如一段代码,是每次逻辑操作都必须调用的,比如循环1000次的某个非核心业务逻辑操作。这样的代码如果包在事务中,势必造成事务太大,导致出现一些难以考虑周全的异常情况。所以这个事务这个级别的传播级别就派上用场了。用当前级别的事务模板抱起来就可以了。

比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,
那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而它以非事务的状态运行完,再继续ServiceA.methodA的事务。

6、PROPAGATION_NEVER

不能在事务中运行。该传播级别要求上下文中不能存在事务,一旦有事务,就抛出runtime异常,强制停止执行!

假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,那么ServiceB.methodB就要抛出异常了。

7、PROPAGATION_NESTED

理解Nested的关键是savepoint。
它与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与它的父事务相互独立,
而Nested的事务和它的父事务是相依的,它的提交是要等和它的父事务一块提交的。也就是说,如果父事务最后回滚,它也要回滚的。

而Nested事务的好处是它有一个savepoint。

ServiceA {

    @Transactional (propagation = Propagation.REQUIRED ) 
    void methodA() {
        try {
            // savepoint
            ServiceB.methodB(); // PROPAGATION_NESTED 级别
        } catch (SomeException) {
            // 执行其他业务, 如 ServiceC.methodC();
        }
    }
}

也就是说ServiceB.methodB失败后进行回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如ServiceC.methodC,继续执行,来尝试完成自己的事务。但是这个事务并没有在EJB标准中定义。

二、Spring事务的五种隔离级别

1、ISOLATION_DEFAULT

这是一个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。

另外4个与 JDBC 的隔离级别相对应。

2、ISOLATION_READ_UNCOMMITTED

这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
这种隔离级别会产生脏读,不可重复读和幻读。

3、 ISOLATION_READ_COMMITTED

保证一个事务修改的数据提交后才能被另外一个事务读取,其它事务不能读取该事务未提交的数据。

4、ISOLATION_REPEATABLE_READ

保证一个事务不能读取另一个事务未提交的数据,避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。

这种事务隔离级别可以防止脏读,不可重复读,但是可能出现幻读。

5、ISOLATION_SERIALIZABLE

这是最可靠的但是代价花费最高的事务隔离级别,事务被处理为顺序执行。
除了可防止脏读,不可重复读外,还避免了幻读。

三、什么是脏数据,脏读,不可重复读,幻读

脏读

指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据, 那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。

不可重复读

指在一个事务内,多次读同一数据,在这个事务还没有结束时,另外一个事务也访问该同一数据,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

幻读

当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。



原文:
Spring事务传播机制&隔离级别

Spring五个事务隔离级别和七个事务传播行为

猜你喜欢

转载自blog.csdn.net/zhouxukun123/article/details/79874797