SpringBoot-事物-传播行为
Spring 有 7 种事务传播行为,描述的是:调用一个事务方法时,如何处理当前已有的事务。以下默认通过 Spring 代理调用、使用同一个事务管理器。
| 传播行为 | 当前没有事务 | 当前已有事务 | 记法 |
|---|---|---|---|
| REQUIRED(默认) | 新建事务 | 加入原事务 | 有就加入,没有就建 |
| REQUIRES_NEW | 新建事务 | 挂起原事务,另建事务 | 总是独立新建 |
| NESTED | 新建事务 | 在原事务内建立保存点 | 内层可退回保存点 |
| SUPPORTS | 无事务执行 | 加入原事务 | 随外层 |
| NOT_SUPPORTED | 无事务执行 | 挂起原事务,无事务执行 | 不用事务 |
| MANDATORY | 报错 | 加入原事务 | 必须已有 |
| NEVER | 无事务执行 | 报错 | 禁止已有 |
常见组合与选择。共 10 种组合。默认 A 通过代理调用另一个 Bean 的 B,使用同一个事务管理器、同一线程;NESTED 需要底层支持。
| A → B | 实际效果 | 使用场景 |
|---|---|---|
REQUIRED → REQUIRED |
共用一个事务,一起提交或回滚。B 的异常经过事务拦截器并将事务标记为只能回滚后,A 即使 catch 也无法正常提交 | 创建订单+扣库存,需要一起成败 |
REQUIRED → REQUIRES_NEW |
挂起 A 的事务,B 独立开启事务。B 已提交的修改不受 A 回滚影响;B 异常外抛仍可能触发 A 回滚 | 业务处理+需要独立保留的操作日志 |
REQUIRED → NESTED |
同一个物理事务,B 建立保存点。B 可局部回滚,A 处理异常后可继续;A 最终回滚,B 也回滚 | 保存主记录+允许失败的可选附加信息 |
A 无事务 → REQUIRED |
B 自己开启事务,范围只覆盖 B;A 后续失败不能撤销 B 已提交的修改 | 无事务的入口调用一个需要保证原子性的业务操作 |
REQUIRES_NEW → REQUIRED |
B 加入 A 的事务,二者共用一个事务 | A 独立执行业务补偿,B 的修改与 A 一起成败 |
REQUIRES_NEW → REQUIRES_NEW |
挂起 A 的事务,B 再开启独立事务;B 结束后恢复 A | A 执行业务补偿,B 独立保存日志 |
REQUIRED → NOT_SUPPORTED |
挂起 A 的事务,B 无事务执行;A 回滚不能撤销 B 已提交的修改 | B 查询不要求与 A 保持同一事务视图的辅助信息 |
REQUIRED → NEVER |
当前有事务,调用 B 时直接报错,B 方法体不执行 | B 明确禁止在事务中调用,检查调用方式是否合规 |
A 无事务 → MANDATORY |
当前没有事务,调用 B 时直接报错,B 方法体不执行 | 扣款方法必须参与上层转账事务,禁止单独调用 |
SUPPORTS → REQUIRED |
A 无事务则 B 新建;A 已加入上游事务则 B 也加入 | A 可以有事务或无事务执行,但 B 的修改必须有事务 |
不用背组合,记住每种行为,再逐层判断。
| 行为 | 怎么记 | 什么时候选 |
|---|---|---|
| REQUIRED | 有就加入,没有就建 | 默认选择,多个操作需要一起成败 |
| REQUIRES_NEW | 总是另开一个 | 需要独立提交,例如保留失败操作的日志 |
| NESTED | 同一事务,设置存档点 | 内层允许失败,外层处理异常后继续 |
| SUPPORTS | 随外层 | 有事务就参与,没有也能执行 |
| NOT_SUPPORTED | 暂停事务再执行 | 明确要求当前方法不参与事务 |
| MANDATORY | 没事务不准进 | 必须由上层事务统一管理,例如转账中的扣款 |
| NEVER | 有事务不准进 | 明确禁止在事务中调用 |
重点区分前三个,用“订单+附加信息”记:
REQUIRED:绑在一起,失败一起回滚。REQUIRES_NEW:各自结账,B 已提交,A 回滚也撤不掉。NESTED:中途存档,B 可以退回存档点;A 最终回滚,仍然全部撤销。
看组合时,只问一句:
走到 B 时有没有事务?B 要加入、另开,还是拒绝它?
实际开发优先用 REQUIRED,有明确的独立提交或局部回滚需求,再考虑另外两种。

浙公网安备 33010602011771号