Spring 基础 事务说明

Spring 基础 事务说明

一、事务简介

事务其实是一个并发控制单位,是用户定义的一个操作序列,这些操作要么全部完成,要不全部不完成,是一个不可分割的工作单位。事务有 ACID 四个特性,即:

  1. Atomicity(原子性):事务中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。
  2. 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
  3. 事务隔离(Isolation):多个事务之间是独立的,不相互影响的。
  4. 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

二、Spring 事务的管理方式

2.1、编程式事务

先看个例子

@Autowired
private PlatformTransactionManager transactionManager;
public void transactionDemo() {
    // 开始事务
    TransactionStatus transactionStatus = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
    try {
          // TODO 业务代码
          
          // 提交事务
          this.transactionManager.commit(transactionStatus);
    } catch (Exception e) {
          // 回滚事务
          this.transactionManager.rollback(transactionStatus);
    }
}
  • PlatformTransactionManager:(平台)事务管理器,Spring 事务策略的核心。
  • TransactionDefinition:事务定义信息(事务隔离级别、传播行为、回滚超时、是否只读、回滚规则)。
  • TransactionStatus:事务运行状态。
2.2、声明式事务

通过 AOP 实现(基于@Transactional 的全注解方式使用最多)。

  • @Transactional 的常用配置参数总结(只列出了 5 个我平时比较常用的):
属性名说明
propagation事务的传播行为,默认值为 REQUIRED,可选的值在上面介绍过
isolation事务的隔离级别,默认值采用 DEFAULT,可选的值在上面介绍过
timeout事务的超时时间,默认值为-1(不会超时)。如果超过该时间限制但事务还没有完成,则自动回滚事务。
readOnly指定事务是否为只读事务,默认值为 false。
rollbackFor用于指定能够触发事务回滚的异常类型,并且可以指定多个异常类型。
  • @Transactional 的使用注意事项总结
  • @Transactional 注解只有作用到 public 方法上事务才生效,不推荐在接口上使用;
  • 避免同一个类中调用 @Transactional 注解的方法,这样会导致事务失效;
  • 正确的设置 @Transactional 的 rollbackFor 和 propagation 属性,否则事务可能会回滚失败;
  • 被 @Transactional 注解的方法所在的类必须被 Spring 管理,否则不生效;
  • 底层使用的数据库必须支持事务机制,否则不生效;

三、Spring 中的隔离级别

TransactionDefinition 接口中定义了五个表示隔离级别的常量:

public interface TransactionDefinition {
    ......
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    ......
}
  1. TransactionDefinition.ISOLATION_DEFAULT :使用后端数据库默认的隔离级别,MySQL 默认采用的 REPEATABLE_READ 隔离级别 Oracle 默认采用的 READ_COMMITTED 隔离级别.
  2. TransactionDefinition.ISOLATION_READ_UNCOMMITTED :最低的隔离级别,使用这个隔离级别很少,因为它允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
  3. TransactionDefinition.ISOLATION_READ_COMMITTED : 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
  4. TransactionDefinition.ISOLATION_REPEATABLE_READ : 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  5. TransactionDefinition.ISOLATION_SERIALIZABLE : 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

四、Spring 事务传播机制

事务的传播机制说明如下:

  1. REQUIRED:默认值;如果当前上下文中存在事务,那么加入该事务,如果不存在事务,创建一个事务。
  2. SUPPORTS:如果当前上下文存在事务,则支持事务加入事务,如果不存在事务,则使用非事务的方式执行。
  3. MANDATORY:如果当前上下文中存在事务,否则抛出异常。
  4. REQUIRES_NEW:每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。
  5. NOT_SUPPORTED:如果当前上下文中存在事务,则挂起当前事务,然后新的方法在没有事务的环境中执行。
  6. NEVER:如果当前上下文中存在事务,则抛出异常,否则在无事务环境上执行代码。
  7. NESTED:如果当前上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。

五、Spring 事务失效场景

  1. 抛出编译异常
    如果@Transactional 没有特别指定,Spring 只会在遇到运行时异常RuntimeException或者error时进行回滚,而IOException等编译异常不会影响回滚。
    • 解决方法,指定回滚异常:@Transactional(rollbackFor = Exception.class)
  2. 方法本身捕获了异常
  3. 同一类中的方法调用
    Spring的事务管理功能是通过动态代理实现的,而Spring默认使用JDK动态代理,而JDK动态代理采用接口实现的方式,通过反射调用目标类。简单理解,就是saveUser()方法中调用this.doInsert(),这里的this是被真实对象,所以会直接走doInsert的业务逻辑,而不会走切面逻辑,所以事务失败。
    • 解决方法:解决方法可以是直接在启动方法上添加 @Transactional 注解
  4. 方法使用 final 或 static关键字
  5. 方法不是public
    如果方法不是public,Spring事务也会失败,因为Spring的事务管理源码AbstractFallbackTransactionAttributeSource中有判断computeTransactionAttribute()。如果目标方法不是公共的,则TransactionAttribute返回null。
  6. 错误使用传播机制
    Spring事务的传播机制是指在多个事务方法相互调用时,确定事务应该如何传播的策略。Spring提供了七种事务传播机制:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。如果不知道这些传播策略的原理,很可能会导致交易失败。
  7. 没有被Spring管理
  8. 多线程调用
    我们说的同一个事务,其实是指同一个数据库连接,只有拥有同一个数据库连接才能同时提交和回滚。如果在不同的线程,拿到的数据库连接肯定是不一样的,所以是不同的事务。

参考:https://juejin.cn/post/7179080622504149029
https://javaguide.cn/system-design/framework/spring/spring-transaction.html


若有凝问或错误,请指出,我好及时改正,让我们一起进步!
email : binary_space@126.com
qq : 103 586 2795
敲门砖: 代码谱写人生

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

征客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值