1. 事务传播机制的本质理解
第一次接触Spring事务时,最让我困惑的就是这个"PROPAGATION_REQUIRES_NEW"的传播行为。当时在支付系统中遇到个场景:支付主流程需要记录操作日志,但日志记录失败不能影响支付核心业务。我的第一反应是直接try-catch包住日志代码,直到发现日志表里总是缺少记录才意识到问题——事务回滚把日志也带走了。
事务传播机制本质上解决的是"业务边界"问题。就像组织工作交接,不同部门(业务方法)协作时,需要明确:
- 新任务是否要开独立会议(新建事务)
- 是否沿用现有会议记录(加入当前事务)
- 还是完全另起炉灶(独立事务)
O(2)这个命名很有意思,它暗示着两层事务嵌套的场景。实际开发中,这种需要分离业务操作的情况远比想象中常见:
- 日志记录与核心业务分离(如支付日志)
- 数据统计与数据写入分离(如订单量统计)
- 次要流程与主流程分离(如发放优惠券)
关键认知:事务传播不是技术炫技,而是业务语义的代码映射。选择哪种传播行为,取决于业务上是否需要"同生共死"。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. REQUIRES_NEW的实战解剖
2.1 工作机制深度解析
当方法A(主事务)调用方法B(REQUIRES_NEW)时:
- 方法A执行到调用点时会挂起当前事务(Suspend)
- 为方法B创建全新事务(New Transaction)
- 方法B执行完毕后再恢复方法A的事务(Resume)
这个机制会产生几个重要特性:
- 两个事务完全独立,有各自的隔离级别和锁
- 方法B的提交/回滚不会影响方法A
- 方法A回滚时,已提交的方法B不受影响
java复制// 典型代码结构示例
@Transactional
public void processPayment(PaymentRequest request) {
// 主事务操作
paymentService.execute(request);
try {
// 独立事务操作
auditLogService.recordOperation(request);
} catch (Exception e) {
// 日志失败不影响主流程
log.error("Audit log failed", e);
}
}
@Service
public class AuditLogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void recordOperation(PaymentRequest request) {
// 日志记录实现
}
}
2.2 必须掌握的四个技术细节
- **连接持有问题
