Spring 事务传播行为和隔离级别的应用

一言蔽之

对Spring事务了解一直处于理论阶段,几个事务传播行为(propagation behaviors),几个隔离级别(isolation levels)看了又忘,忘了又看。近期的开发中遇到了几个有趣的例子,拿出来晒晒。

具体应用

1. 在catch块中,继续进行数据库操作

场景

以下是简化后的Kotlin代码
execute()在事务内执行
doSomeThing()可能会抛出RuntimeException
fail() 会对数据库有一些修改操作


@Transactional
override fun execute() {
    try {
        doSomeThing()
    } catch (e: Exception) {
        fail()
    }
}

override fun fail() {
   saveLogToDB()
}

问题
如果doSomeThing()抛出RuntimeException,fail()在执行数据库操作时,会抛出异常:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

分析&思路

  1. 方法saveLogToDB()执行时事务已经被标记为rollback-only
  2. saveLogToDB()使用的事务是在execute()方法执行之前创建的
  3. doSomeThing()执行的某个步骤中,因为触发异常,事务被标记为rollback-only
  4. 那么,为了saveLogToDB()能够保存数据到数据库,就不能够使用execute()方法的事务了。

回忆以下有哪些事务的传播行为:

// 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
    // @Transactional 注解默认采用这个方案
    REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

    // 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
    SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

    // 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
    MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

     // 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
    REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

    // 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
    NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

    // 以非事务方式运行,如果当前存在事务,则抛出异常。
    NEVER(TransactionDefinition.PROPAGATION_NEVER),

    // 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于REQUIRED
    // 并非所有的TransactionManager都能支持这个传播级别
    NESTED(TransactionDefinition.PROPAGATION_NESTED);

作者:whthomas
链接:https://www.jianshu.com/p/e56b440e9eb6
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

显然,这里需要使用REQUIRES_NEW传播行为。

解决
fail()方法上加上事务,并让propagation = REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRES_NEW)
override fun fail() {
   saveLogToDB()
}

注意:同一个类中,方法间调用,事务AOP生效的前提条件是使用CGLIB方式实现AOP。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 事务,是为了保障逻辑处理的原子性、一致性、隔离性、永久性。 通过事务控制,可以避免因为逻辑处理失败而导致产生脏数据...
    uzip柚子皮阅读 4,734评论 3 16
  • 事务的嵌套概念 所谓事务的嵌套就是两个事务方法之间相互调用。spring事务开启 ,或者是基于接口的或者是基于类的...
    jackcooper阅读 1,453评论 0 10
  • 很多人喜欢这篇文章,特此同步过来 由浅入深谈论spring事务 前言 这篇其实也要归纳到《常识》系列中,但这重点又...
    码农戏码阅读 4,802评论 2 59
  • 从前有一个老人,他有三个儿子。 有一天,三个儿子开始比绝招,大儿子出了一个谜题,树上七只猴,地下一只猴,一共有几只...
    猴一棒阅读 230评论 0 2
  • 了解了穷文富武的概念。 高考的公平在于比起大城市的优良素质教育,给广大农村及不富裕的地区的孩子一个只要肯下功夫把书...
    cuijieshi阅读 284评论 0 0