Spring 事务 7 种传播行为

发布时间:2026/7/28 2:58:54
Spring 事务 7 种传播行为 一、基础概念事务传播行为多个事务方法互相调用时事务如何传递、创建、复用的规则当方法 A 调用方法 BA、B 都带有Transactional传播行为决定 B 是沿用 A 的事务、新建事务、还是不使用事务。核心入口TransactionDefinition接口定义 7 个常量Transactional(propagation Propagation.REQUIRED)指定。二、7 种传播行为完整详解执行逻辑 场景 区别1. REQUIRED默认值最常用规则如果当前存在事务外层有事务复用外层事务内外是同一个事务如果当前无事务自己新建一个独立事务。执行案例外层无事务 → 新建事务执行 B外层 A 有事务 → B 加入 A 事务A/B 任意一处异常整体一起回滚。适用场景90% 普通业务增删改订单、用户、库存所有操作必须同生共死。2. REQUIRES_NEW规则永远创建全新独立事务不管外层是否存在事务外层事务会被挂起等内层新事务执行完成后再恢复外层事务。 内外两个事务完全隔离互不影响。执行案例A (REQUIRED) 调用 B (REQUIRES_NEW)A 开启事务执行到 B 时挂起 A 事务B 新建独立事务B 正常提交 / 异常回滚都不会影响 AB 执行完毕恢复 A 事务继续执行后续 A 抛异常回滚不会回滚 B 已经提交的数据。适用场景日志记录、操作流水、异步记录。 例下单失败回滚订单但需要保存失败日志日志不能跟着订单一起回滚日志方法使用REQUIRES_NEW。3. SUPPORTS规则当前有事务沿用外层事务当前无事务直接以非事务方式执行无事务。适用场景查询类接口select。查询不需要事务若外层有事务查询嵌套在更新业务里则加入外层事务保证数据一致性。4. NOT_SUPPORTED规则强制以非事务运行如果外层存在事务直接挂起外层事务内层方法无事务执行。适用场景大数据导出、批量查询、读取海量数据不需要事务同时不占用外层事务连接。例事务中导出百万条数据避免长时间占用数据库事务连接。5. MANDATORY强制规则必须存在外层事务否则直接抛出异常不能单独运行。适用场景子业务必须依赖外层主事务禁止单独调用。例扣减库存逻辑必须嵌套在创建订单主事务中禁止外部单独调用扣库存方法。6. NEVER规则绝对不允许存在外层事务如果外层存在事务直接抛异常无外层事务则正常无事务执行。适用场景明确禁止被事务包裹的方法。例批量删除历史归档数据逻辑独立不允许嵌套在其他事务中导致长事务锁表。7. NESTED嵌套事务规则外层无事务新建独立事务等价于 REQUIRED外层存在事务创建嵌套子事务保存点 SavePoint不是独立新事务。核心特性和 REQUIRES_NEW 最大区别子事务回滚只会回滚到自身保存点不会导致外层事务回滚外层事务回滚会连带所有嵌套子事务一起全部回滚共用同一个数据库连接没有挂起事务操作。适用场景主业务流程下存在多个可独立回滚的子步骤。例创建订单主流程包含「生成订单、发放优惠券、扣积分」三个子操作优惠券发放失败只回滚优惠券不回滚订单但如果订单创建失败优惠券、积分全部回滚。三、REQUIRES_NEW VS NESTED 高频对比面试必问表格对比维度REQUIRES_NEWNESTED事务关系两个完全独立事务互不影响外层主事务 子保存点从属关系数据库连接新建连接外层事务挂起共用同一个数据库连接内层回滚内层回滚外层事务不受任何影响内层回滚仅回滚自身外层可继续提交外层回滚外层回滚不影响已提交的内层事务外层回滚所有嵌套子事务全部回滚底层原理独立事务独立 commit/rollback基于 JDBC SavePoint 保存点实现四、7 种传播行为快速速查表表格传播行为外层有事务外层无事务核心特点REQUIRED默认加入外层事务新建事务同生共死通用REQUIRES_NEW挂起外层新建独立事务新建事务内外完全隔离SUPPORTS加入外层事务无事务执行适合查询NOT_SUPPORTED挂起外层无事务执行无事务执行大数据查询导出MANDATORY加入外层事务直接抛异常必须嵌套事务调用NEVER直接抛异常无事务执行禁止嵌套在事务中NESTED创建保存点子事务新建事务子事务可单独回滚外层回滚连带子事务五、企业开发使用规范增删改业务默认REQUIRED记录操作日志、异常流水REQUIRES_NEW单纯查询接口SUPPORTS大数据批量读取 / 导出NOT_SUPPORTED底层子操作不允许单独调用MANDATORY归档清理、独立批量操作NEVER主流程下多步骤可局部回滚NESTED六、高频面试题补充NESTED 依赖数据库支持吗需要底层 JDBC 驱动支持 SavePoint 保存点MySQL、Oracle 均支持。为什么日志要用 REQUIRES_NEW不用 NESTED业务操作失败回滚时日志需要永久留存NESTED 外层回滚会连带日志一起回滚无法保存日志因此日志场景必须用 REQUIRES_NEW。MANDATORY 和 NEVER 的区别MANDATORY必须有外层事务无事务报错 NEVER绝对不能有外层事务有事务报错。两者约束完全相反。