REQUIRES_NEW的核心机制是挂起当前事务并开启全新事务,而非简单另起炉灶;它通过暂存外层事务状态、获取新连接、独立执行T2,确保T1与T2互不影响,典型用于日志记录、优惠券发放等需强可靠性的场景。

REQUIRES_NEW 的核心机制,是“挂起当前事务、开启全新事务”,不是简单地“另起炉灶”。它在嵌套调用中表现得尤为明显——外层事务不会被终止,而是被临时冻结,等内层事务彻底结束(提交或回滚)后,再恢复执行。
挂起不是销毁,是上下文切换
Spring 在执行带有 @Transactional(propagation = Propagation.REQUIRES_NEW) 的方法时,会做三件事:
- 检查当前线程绑定的事务资源(比如 DataSourceTransactionManager 持有的 Connection)
- 把当前事务的同步器(TransactionSynchronizationManager)状态保存起来,包括 Connection、isActualTransactionActive 标志、各类回调等
- 新开一个数据库连接(或从连接池获取新连接),启动完全独立的事务上下文
这个过程叫“挂起(suspend)”,不是关闭连接或释放资源,只是让外层事务暂时失去对线程的控制权。就像暂停播放视频后切到另一个 App,原视频仍在缓冲区,切回来就能继续播。
嵌套调用中事务隔离的真实表现
假设 methodA 被 @Transactional(默认 REQUIRED)修饰,内部调用 methodB,而 methodB 声明为 REQUIRES_NEW:
立即学习“Java免费学习笔记(深入)”;
- methodA 启动事务 T1,拿到连接 C1
- 进入 methodB 时,Spring 暂存 T1 的所有状态,断开 C1 与当前线程的绑定
- methodB 获取新连接 C2,开启事务 T2,T2 的提交/回滚互不影响 T1
- T2 结束后,Spring 把 C1 重新绑定回线程,T1 继续执行
关键点:T2 的成功提交,不会让 T1 中已写但未提交的数据提前可见;T1 后续若回滚,只影响 T1 写入的数据,T2 的数据早已落库。
为什么挂起机制容易被误解?
常见误判往往来自以下操作:
- 同一类内 this 调用:methodA 直接调用 this.methodB(),绕过 Spring AOP 代理,REQUIRES_NEW 失效,实际仍是同一个事务
- 异常未抛出或被吞掉:methodB 内发生异常但被 try-catch 吞掉且没 rethrow,T2 不会回滚,T1 也感知不到失败
- 非 public 方法加注解:@Transactional 只对 public 方法生效,private/protected 上的注解会被忽略
这些都不是挂起机制本身的问题,而是使用方式偏离了 Spring 事务代理的生效前提。
REQUIRES_NEW 的典型适用场景
它存在的意义,就是解决“必须落地、不能被撤回”的操作:
- 记录操作日志、审计流水(即使主业务失败,日志也要留痕)
- 发放优惠券、更新积分余额(需独立幂等,不随订单取消而失效)
- 异步任务触发前的状态快照(如生成任务 ID 并持久化,后续发 MQ 不依赖主事务)
本质上,它是用一次连接切换和事务隔离,换来了业务语义上的强可靠性保障。


















