Spring 事务是业务开发的基石,所有支付、订单、库存、对账系统都依赖事务保证数据一致性。本文系统性梳理Spring 事务底层执行流程、两种事务实现方式、优缺点与适用场景、7种传播机制、5种隔离级别,内容精炼、无废话、适合面试背诵 + 生产落地。
一、Spring 事务核心底层执行逻辑
1.1 核心本质
Spring 事务底层基于 AOP 动态代理 实现,属于典型的横切逻辑增强:不修改业务代码,通过代理环绕实现事务的开启、提交、回滚。
1.2 完整执行流程(必考)
-
代理拦截 :调用带有
@Transactional的方法时,Spring 代理拦截请求。 -
事务判断:根据当前线程是否存在事务、传播级别判断是否需要新建事务。
-
开启事务:获取数据库连接、关闭自动提交(autoCommit=false)。
-
执行目标业务方法:执行数据库增删改逻辑。
-
正常返回 :无异常 → 手动提交事务、释放连接。
-
抛出异常 :命中回滚规则 → 事务回滚,杜绝脏数据。
核心前提 :Spring 事务仅对 public 方法、外部调用、代理对象调用 生效。
二、Spring 两种事务实现方式
2.1 编程式事务(手动编码)
通过 TransactionTemplate 手动编写事务逻辑,全程手动控制开启、提交、回滚。
示例
transactionTemplate.execute(status -> {
// 业务数据库操作
try {
// 增删改逻辑
} catch (Exception e) {
status.setRollbackOnly();
}
return null;
});
优点
-
细粒度极高,可以精准控制某段代码事务
-
无 AOP 失效问题,执行稳定可靠
-
灵活度高,可动态控制事务规则
缺点
-
代码侵入性极强,冗余代码多
-
每个业务都要写事务模板,开发效率低
适用场景
复杂动态事务、特殊片段事务、框架注解事务无法满足的极端场景。
2.2 声明式事务(注解事务 @Transactional)------主流
基于 AOP 实现,通过 @Transactional 注解声明事务,无需手动写事务代码。
优点
-
零侵入:业务代码干净,符合开闭原则
-
配置简单、统一规范、维护成本低
-
全局统一管控,适合绝大多数业务场景
缺点
-
基于 AOP 代理,存在大量事务失效场景
-
粒度较粗,默认作用于整个方法
-
隐式执行,排查问题难度高于手动事务
适用场景
95% 以上常规业务:订单、支付、库存、账务、CRUD 业务,是企业开发标准方案。
三、Spring 事务传播机制(7种传播级别)
传播机制核心作用 :解决多个事务方法嵌套调用时,事务如何传递、是否共用、是否新建 的问题。
分为三类:支持当前事务、不支持事务、嵌套事务。
3.1 支持当前事务(常用)
1. REQUIRED(默认)
有事务就加入,无事务就新建。Spring 默认级别,最常用。
-
外层有事务:内外合并为同一个事务,一滚全滚
-
外层无事务:自己新建独立事务
2. SUPPORTS
有事务就加入,无事务就非事务运行。
3. MANDATORY
强制要求在事务内运行,外层无事务直接抛异常。
3.2 不支持当前事务
4. REQUIRES_NEW
无论外层是否有事务,始终新建独立事务,内外事务相互独立、互不影响。
外层回滚不影响内层,内层异常也不影响外层(独立提交/回滚)。
5. NOT_SUPPORTED
始终以非事务方式执行,挂起外层事务。
6. NEVER
强制非事务运行,检测到外层有事务直接报错。
3.3 嵌套事务(特殊)
7. NESTED
外层有事务:嵌套在当前事务中,存在独立保存点。
-
内层异常可单独回滚,不影响外层
-
外层异常,内层必须全部回滚
外层无事务:新建事务(类似 REQUIRED)
注意:仅支持 MySQL、JDBC,不支持分布式事务。
四、事务隔离级别(5种)
隔离级别用来解决并发事务引发的脏读、不可重复读、幻读问题,是数据库并发控制核心。
三大并发问题(由差到优):
-
脏读 :一个事务读到另一个事务未提交的脏数据
-
不可重复读:同一事务内,两次查询结果不一致(被其他事务 update)
-
幻读:同一事务内,两次查询行数不一致(被其他事务 insert/delete)
4.1 五种隔离级别详解
1. DEFAULT(Spring 默认)
跟随数据库默认隔离级别。MySQL 默认 RR(可重复读)。
2. READ_UNCOMMITTED(读未提交)
最低级别,可读到未提交数据。脏读、不可重复读、幻读全部存在,生产几乎不用。
3. READ_COMMITTED(读已提交 / RC)
只能读取已提交数据。
-
解决:脏读
-
存在:不可重复读、幻读
Oracle 默认隔离级别。
4. REPEATABLE_READ(可重复读 / RR,MySQL默认)
保证同一事务多次读取数据一致。
-
解决:脏读、不可重复读
-
存在:幻读(MySQL 通过间隙锁极大缓解,但未彻底解决)
5. SERIALIZABLE(串行化)
最高级别,事务串行执行,彻底解决三大问题。
缺点:性能极差、锁竞争严重,并发场景几乎不用。
五、各隔离级别优劣与适用场景
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 适用场景 |
|---|---|---|---|---|
| READ_UNCOMMITTED | 有 | 有 | 有 | 无生产用途 |
| READ_COMMITTED | 无 | 有 | 有 | 高并发、普通业务、查询多 |
| REPEATABLE_READ | 无 | 无 | 弱解决 | 支付、订单、账务(MySQL默认) |
| SERIALIZABLE | 无 | 无 | 无 | 极低并发、强一致性场景 |
六、补充:Spring 事务高频失效场景
因为事务基于 AOP,所以以下场景事务完全不生效:
-
方法不是 public
-
同类内部 this 调用
-
try-catch 吞掉异常未抛出
-
默认只回滚 RuntimeException,普通 Exception 不回滚
-
传播机制配置错误导致事务挂起
七、全文总结
1. 事务原理:Spring 事务基于 AOP 动态代理,环绕拦截方法,自动开启、提交、回滚事务。
2. 两种方式:编程式灵活但侵入高;声明式注解优雅、统一规范、企业主流。
3. 传播机制:核心解决事务嵌套问题,默认 REQUIRED;REQUIRES_NEW 独立事务;NESTED 嵌套保存点。
4. 隔离级别:解决并发事务三大问题;MySQL 默认 RR 可重复读,平衡一致性与性能。
5. 取舍思想:高并发选 RC,金融一致性选 RR,绝对一致极低并发选串行化。