Skip to content
Carol's Blog
Go back

Spring事务传播机制

Edit page

Spring 事务的传播机制(Propagation Behavior)是事务管理中一个极其核心且容易出问题的概念,它定义了当多个事务方法互相调用时,事务该如何传播、合并或分离。理解其行为对构建健壮、数据一致的应用至关重要。

Spring 使用 @Transactional 注解(或其 XML 等价配置)定义事务,propagation 属性用来指定传播行为,其取值来源于 Propagation 枚举类。


核心传播行为(7 种):

1.REQUIRED (默认值)

@Transactional(propagation = Propagation.REQUIRED)
public void mainBusiness() {
    updateA(); // REQUIRED - 加入mainBusiness的事务(如果存在)或新建
    updateB(); // REQUIRED - 同上
}

2.SUPPORTS

@Transactional(propagation = Propagation.REQUIRED)
public void updateData() {
    queryForLog(); // SUPPORTS - 加入updateData的事务
    // update something
}

public void justQuery() {
    queryForLog(); // SUPPORTS - 无外层事务,非事务执行
}

3.MANDATORY

public void outerService() {
    // 没有声明事务
    criticalOperation(); // MANDATORY - 直接抛出异常!因为没有事务存在
}

@Transactional
public void anotherService() {
    criticalOperation(); // MANDATORY - 成功加入已有事务
}

4.REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRED)
public void processOrder() {
    // 操作订单表...
    try {
        auditService.logAction(); // REQUIRES_NEW - 暂停外层事务,启动新事务
    } catch (Exception auditEx) {
        // 处理审计异常,不影响订单回滚
    }
    // 发生其他异常,回滚外层事务(操作订单表失败)
}
// 审计日志可能成功,即使订单事务失败

5.NOT_SUPPORTED

@Transactional(propagation = Propagation.REQUIRED)
public void syncData() {
    updateLocal(); // 在事务内
    callExternalSystem(); // NOT_SUPPORTED - 暂停事务,非事务方式执行
    // 后续操作仍在原事务内,但外部调用无事务保障
}

6.NEVER

@Transactional(propagation = Propagation.REQUIRED)
public void businessWithSensitiveCall() {
    // ... 一些操作
    sensitiveMaintenance(); // NEVER - 抛出异常!因为businessWithSensitiveCall开启了事务
}

public void standaloneMaintenance() {
    sensitiveMaintenance(); // NEVER - 无事务,成功执行
}

7.NESTED

@Transactional(propagation = Propagation.REQUIRED)
public void complexOperation() {
    step1(); // REQUIRED or NESTED (效果相同)
    try {
        optionalStep(); // NESTED - 在复杂操作的大事务内部创建嵌套事务点
    } catch (StepException e) {
        // 只回滚optionalStep做的数据库操作(依赖保存点),外部事务未回滚!
        log.error("Optional step failed, skipping", e);
    }
    step3(); // 不受optionalStep失败的影响,继续在外部事务中执行
}

关键点总结与注意事项:

  1. 默认与推荐: REQUIRED 是默认值,满足 80% 的常规业务场景需求。

  2. 事务的创建与加入: REQUIREDSUPPORTSMANDATORYNESTED 会加入或不创建事务;REQUIRES_NEWNOT_SUPPORTED 会暂停外部事务;NEVER 拒绝加入。

  3. REQUIRES_NEW vs NESTED

    • 独立性: REQUIRES_NEW 是完全独立的两个物理事务,各自提交/回滚(外部异常不影响它提交,除非自己内部失败)。NESTED 是同一个物理事务内部的逻辑划分(外部事务回滚必然导致嵌套事务回滚)。

    • 数据库连接: REQUIRES_NEW 通常需要获取一个新的数据库连接(性能开销大)。NESTED 使用同一个连接,仅设置保存点(性能开销小)。

    • 应用场景: 需要操作完全独立 => REQUIRES_NEW;需要部分步骤可选回滚 => NESTED

  4. SUPPORTS vs NOT_SUPPORTED vs NEVER 是否支持在事务内运行?需要控制事务性。

  5. MANDATORY vs NEVER 强制必须有事务 vs 强制必须不能有事务。

  6. 代理机制: 同一个类内部方法互相调用时,基于代理(AOP)的事务行为不会生效! 因为内部调用是 this,绕过代理对象。

  7. 平台差异: NESTED 依赖于底层数据库是否支持保存点。

  8. 与隔离级别的区分: 传播机制解决的是事务边界传播的问题;隔离级别解决的是并发事务之间的可见性问题(脏读、不可重复读、幻读)。

  9. 回滚规则: 传播机制定义了事务如何传播,但最终某个具体事务回滚与否还依赖于声明的回滚规则(rollbackFor/noRollbackFor) 以及方法执行过程中是否抛出符合这些规则的异常。

实际选型建议:

透彻理解Spring事务传播行为是避免分布式事务中数据不一致的基石,建议结合实际问题场景进行实践体会。


Edit page
Share this post on:

Previous Post
Spring MVC
Next Post
数据库事务的隔离级别有哪些?