Spring事务的传播机制和隔离级别

一、事务的传播机制

为什么会有传播机制

spring 对事务的控制,是使用 aop 切面实现的,我们不用关心事务的开始,提交 ,回滚,只需要在方法上加 @Transactional 注解,这时候就有问题了。

  • 场景一: serviceA 方法调用了 serviceB 方法,但两个方法都有事务,这个时候如果 serviceB 方法异常,是让 serviceB 方法提交,还是两个一起回滚。
  • 场景二:serviceA 方法调用了 serviceB 方法,但是只有 serviceA 方法加了事务,是否把 serviceB 也加入 serviceA 的事务,如果 serviceB 异常,是否回滚 serviceA 。
  • 场景三:serviceA 方法调用了 serviceB 方法,两者都有事务,serviceB 已经正常执行完,但 serviceA 异常,是否需要回滚 serviceB 的数据。
传播机制生效条件

因为Spring是使用AOP来代理事务,是针对于接口或类的,所以在同一个service类中的两个方法的调用,传播机制是不生效的

传播机制类型

下面的类型都是针对于被调用方法来说的,理解起来要想象成两个service方法的调用才可以

REQUIRED (默认)
  • 支持当前事务,如果当前没有事务,则新建事务
  • 如果当前存在事务,则加入当前事务,合并成一个事务
REQUIRES_NEW
  • 新建事务,如果当前存在事务,则把当前事务挂起
  • 这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交
NESTED
  • 如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交
  • 如果当前没有事务,则新建事务
  • 如果它异常,父级可以捕获它的异常而不进行回滚,正常提交
  • 但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别
SUPPORTS
  • 如果当前存在事务,则加入事务
  • 如果当前不存在事务,则以非事务方式运行,这个和不写没区别
NOT_SUPPORTED
  • 以非事务方式运行
  • 如果当前存在事务,则把当前事务挂起
MANDATORY
  • 如果当前存在事务,则运行在当前事务中
  • 如果当前无事务,则抛出异常,也即父级方法必须有事务
NEVER
  • 以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务
一般用得比较多的是

PROPAGATION_REQUIREDREQUIRES_NEW

REQUIRES_NEW 一般用在子方法需要单独事务,暂时找不到例子,以后补充

二、事务的隔离级别

ISOLATION_DEFAULT

这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别
MySQL默认的事务隔离级别为 可重复读(repeatable-read)
Oracle默认的事务隔离级别为 读已提交(read-committed)

另外四个与JDBC的隔离级别相对应:

事务隔离级别脏读不可重复读幻读
读未提交(ISOLATION_READ_UNCOMMITTED)
读已提交(ISOLATION_READ_COMMITTED)
可重复读(ISOLATION_REPEATABLE_READ)
串行化(ISOLATION_SERIALIZABLE)

脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

三、如何切换Spring的传播机制类型

@Transactional注解中的属性propagation可以控制传播机制类型

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.transaction.annotation;

public enum Propagation {
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);

    private final int value;

    private Propagation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值