下面把 **传播行为** 拆成“**有父事务时怎么做**”和“**无父事务时怎么做**”两个维度,比原来的「是否必须有父事务 / 是否会新建事务」更直观——一眼就能看出它在两种场景下的动作差异。 | 传播行为 | **父事务已存在时** | **父事务不存在时** | 典型用途 / 说明 | | ----------------------- | -------------------------------------------------- | ------------------------------------ | ------------------------------------------ | | **`REQUIRED`** *(默认)* | **加入父事务**→ 共提交 / 回滚 | **创建新事务** | 日常业务写操作,保持一致性 | | **`REQUIRES_NEW`** | **挂起父事务**→ **自己新建事务** | 自己新建事务 | 写日志、发送 MQ 等:外层失败也要单独成功 | | **`SUPPORTS`** | 加入父事务 | **非事务方式执行** | 只读查询:有事务跟随一致性,没有就轻量查询 | | **`NOT_SUPPORTED`** | **挂起父事务**→ 非事务方式执行 | 非事务方式执行 | 大批量/耗时操作,避免长事务锁表 | | **`MANDATORY`** | 加入父事务 | **立即抛异常** | 防御性编程:强制要求调用方已开启事务 | | **`NEVER`** | **立即抛异常** | 非事务方式执行 | 禁止在事务里跑的代码(如特殊 DDL) | | **`NESTED`** | 同一物理事务,打 **SAVEPOINT**→ 子回滚只回到保存点 | 创建新事务(与 `REQUIRED` 效果相同) | 分段回滚;需 DB / JDBC 支持保存点 | ### 使用 Tips - **不想被外层事务拖垮** ➜ `REQUIRES_NEW` - **可有可无事务的读操作** ➜ `SUPPORTS` - **耗时任务要彻底裸跑** ➜ `NOT_SUPPORTED` - **局部失败但整体继续** ➜ `NESTED`(保存点) - **强约束外层必须有事务** ➜ `MANDATORY` - **坚决拒绝在事务里执行** ➜ `NEVER` 这样,你只需关心: > *「现在有没有父事务?✚ → 该传播行为会怎么做?」* 就能快速判断是否满足你的业务需求。