暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

01.事务的传播机制

阿亮的日志 2021-04-14
393

前言

上一篇文章主要讲解了mysql中一些事务的基本知识,但是我们在工作中基本是不会直接操作mysql的事务的,而是通过spring框架来处理的。这一篇就来研究下spring中的事务。

知识点

  • spring对于事务的支持
  • 事务的传播机制

面试引导

  • spring执行某个操作,前9次成功,第10次失败。以下分别对应什么传播机制?
    • A:全部回滚
    • B:前9次提交,第10次回滚

1.Spring对于事务的支持

1.1.声明式事务

即我们最常使用的@Transactional注解。

使用@Transactional
注解时一般要标注上如下两个参数

  • rollbackFor: 指定异常回滚。一般是RuntimeException
  • propagation: 事务的隔离级别这个我们一般采用了默认的PROPAGATION_REQUIRED

1.2编程式事务

现在一般没人用了,通过TransactionTemplate
来实现,此处不再赘述

2.事务的传播机制

我们在数据库中使用事务的时候,是通过事务开始-->业务逻辑-->事务结束
这样的流程进行的,是针对不同的单个事务。

而在Java业务代码中,通常是在一个方法上进行的事务操作,通过@Transactional
来实现,因此就涉及到了同一个事务操作涉及到多个方法的调用,

并且多个方法有可能不在一个事务中,那么这多个方法是分别提交各自的事务,还是需要合并到外层的事务一起提交,这就是我们事务的传播机制要做的事务了。

2.1.事务的案例

这里用两个类来演示一个事务的传播

ServiceA:作为事务的发起者,会调用另一个类

ServiceB:被调用者

ClassA

public class ServiceA {

  @Autowired
  private ServiceB b;

  @Transactional
  public void methodA() {
// 一坨数据库操作
    for(int i = 0; i < 51; i++) {
      try {
        b.methodB();
      } catch(Exception e) {
// 打印异常日志
      }
    }
// 一坨数据库操作
  }

}

ClassB

public class ServiceB {

  @Transactional(propagation = PROPAGATION_REQUIRES_NEW)
  public void methodB() {

  }
      
}


这里结合两个常用的事务REQUIRED
REQUIRES_NEW
传播机制,来说明下上面的业务会发生什么

  • REQUIRED

    • @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = RuntimeException.class)

    • 嵌套的事务是独立的事务,不会影响外面的事务

    • B会强制开启一个新事务,A的事务会卡主,执行完B的然后执行A的,若A报错,则B不受影响

    • @Transactional(propagation = Propagation.REQUIRED,rollbackFor = RuntimeException.class)

    • 不管methodB()是否加事务,都会使用A的事务,即A或者B中有失败,都整体回滚

    • REQUIRES_NEW

2.2.事务的传播机制

spring一共定义了7种传播机制。但是我们常用的也就是上面那两种

传播机制作用
PROPAGATION_REQUIREDSpring默认的传播机制,ServiceA.method()-->ServiceB.method,若A和B都声明了事务,则B不会独立开启事务,将B的事务放到A中一起执行,A和B任意一个报错都会整体回滚
PROPAGATION_REQUES_NEWServiceB会强制开启一个新的事务,执行的时候ServiceA会卡主等待B执行完毕之后再继续。若A报错,B不受影响,B报错,A可以选择性的回滚或者提交
PROPAGATION_SUPPORT如果外层有事务,则加入外层事务,如果外层没有事务,则直接使用非事务方式执行。完全依赖外层的事务
PROPAGATION_NOT_SUPPORT该传播机制不支持事务,如果外层存在事务则挂起,执行完当前代码,则恢复外层事务,无论是否异常都不会回滚当前的代码
PROPAGATION_NEVER该传播机制不支持外层事务,即如果外层有事务就抛出异常
PROPAGATION_MANDATORY与NEVER相反,如果外层没有事务,则抛出异常
PROPAGATION_NESTED该传播机制的特点是可以保存状态保存点,当前事务回滚到某一个点,从而避免所有的嵌套事务都回滚,即各自回滚各自的,如果子事务没有把异常吃掉,基本还是会引起全部回滚的。

2.3.问题解答

针对开头的spring传播机制的面试题目,可以有如下解答:

  • A:两个事务都设置为REQUIRED,这个是毋庸置疑的,全部成功或者全部失败
  • B:将B设置为REQUES_NEW,B每次的调用都在独立事务执行,这样即使第10次失败,也只是回顾最后一次的操作,签名都是独立的事务成功了。

参考资料

spring事务的实现http://www.pladios.top/archives/spring%E4%BA%8B%E5%8A%A1%E7%9A%84%E5%AE%9E%E7%8E%B0



关于我

更多内容可关注公众号

  • Github: https://github.com/liangliang1259/common-notes
  • 公众号


文章转载自阿亮的日志,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论