跳到正文
Elaine Blog
返回

声明式事务的传播、隔离与失效场景

Spring 生态与源码

@Transactional 是元数据,真正开启和提交事务的是代理中的 TransactionInterceptor 与事务管理器。调用没有经过代理时,注解不会自动执行。

Table of contents

Open Table of contents

复现自调用失效

OrderService下载的外层方法调用同类 REQUIRES_NEW 方法:

mvn -Dtest=SpringSourceLabTest#selfInvocationDoesNotStartRequiresNewTransaction test

记录型事务管理器只看到一次 BEGIN 和 COMMIT,因为内部 this.audit() 没有再次经过代理。将不同事务边界拆到另一个 Bean,或使用编程式事务表达局部边界。

传播决定如何加入事务

传播行为
REQUIRED有事务就加入,没有就新建
REQUIRES_NEW暂停外层并新建独立事务
NESTED使用保存点,依赖事务管理器支持
SUPPORTS有就加入,没有就非事务执行

REQUIRES_NEW 会额外占用数据库连接。外层持有一条连接、内层再取一条时,连接池容量不足可能死等。

隔离与回滚规则

隔离级别约束并发事务能观察到什么,最终行为还受数据库实现和 SQL 锁影响。默认继承底层数据库隔离,不应无证据地全局改为最高级别。

默认情况下 RuntimeExceptionError 触发回滚,受检异常不回滚。捕获异常后正常返回会提交;需要回滚时重新抛出、声明 rollbackFor 或显式标记。

事务不会跨越所有边界

线程绑定事务不会自动传到新线程,HTTP/RPC 调用也不会共享本地数据库事务。远程一致性要用幂等、Outbox、Saga 或补偿,不要把数据库事务保持到网络调用结束。

Spring 官方事务注解说明明确指出默认代理模式只拦截外部调用。

下一步

阅读Spring MVC 启动映射与参数绑定,继续追踪 Web 请求进入控制器前的基础设施。


分享这篇文章:

上一篇
AOP 代理创建与调用链
下一篇
Spring MVC 启动、映射与参数绑定