异步线程丢失事务是因为Spring事务基于ThreadLocal,@Async新建线程无法继承父线程的事务上下文,导致TransactionSynchronizationManager中无事务资源。

在 Spring 事务中启动异步线程(如用 @Async)会导致事务失效,根本原因是:新线程不继承原事务上下文,Spring 的 TransactionSynchronizationManager 是基于 ThreadLocal 实现的,子线程无法自动获取父线程的事务信息。
为什么异步线程会丢失事务?
Spring 默认使用 ThreadLocal 存储当前事务资源(如数据库连接、事务状态)。当调用 @Async 方法时,Spring 通过线程池新建线程执行,该线程的 ThreadLocal 是空的,既没有绑定数据源连接,也不在任何事务中——哪怕原方法加了 @Transactional。
常见误写:
@Service
public class OrderService {
@Transactional
public void createOrder(Order order) {
orderMapper.insert(order); // ✅ 在事务中
asyncTask.sendNotification(order); // ❌ 异步方法无事务,且不影响上面的 insert 回滚
}
}
@Component
public class AsyncTask {
@Async
public void sendNotification(Order order) {
logMapper.insert(new Log("notify_sent")); // ⚠️ 这个插入不受 createOrder 事务控制
// 若这里抛异常,orderMapper.insert 不会回滚
}
}
正确处理方式:按场景选择策略
1. 异步操作本身不需要事务
这是最常见情况。比如发短信、写日志、调外部接口等「非核心数据一致性」操作,应明确剥离事务:
- 确保异步方法上 不要加
@Transactional - 原事务方法中只做关键 DB 操作,异步调用仅作“事后通知”
- 若异步失败需补偿,改用消息队列 + 本地事务表 或 Saga 模式
2. 异步逻辑必须强依赖当前事务结果(如:事务提交后才发 MQ)
利用 Spring 的事务同步机制,在事务成功提交后触发异步动作:
@Service
public class OrderService {
@Transactional
public void createOrder(Order order) {
orderMapper.insert(order);
// 注册事务提交后的回调
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
asyncTask.sendNotificationAfterCommit(order); // ✅ 保证 order 已落库
}
}
);
}
}
注意:afterCommit() 中不能再操作同一个事务管理器下的 JPA/Hibernate 实体,但可以安全调用 @Async 方法或发 MQ。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
3. 需要在新线程中开启独立事务
如果异步任务自身需要数据库操作且要求事务隔离(例如记录异步任务状态),应显式启用新事务:
- 异步方法上加
@Transactional(propagation = Propagation.REQUIRES_NEW) - 确保该方法由 Spring 代理调用(不能本类 self-invocation)
- 这样它会挂起当前事务(如有),开启自己的事务,失败不影响主流程
避坑提醒
别手动传播 TransactionStatus:试图把 TransactionStatus 传给子线程再绑定是错误的——事务资源(Connection)通常绑定到线程,不可跨线程复用,强行传递会导致连接泄漏或并发异常。
别用普通 new Thread() + @Transactional:Spring 的 AOP 代理对非 Spring 管理的线程完全无效,@Transactional 注解不会生效。
@Async 方法必须是 public 且由 Spring 容器调用:私有方法、this.send() 调用均绕过代理,事务和异步都失效。
事务与异步本质是两个不同维度的控制:事务管数据一致性,异步管执行时机。混用时需清晰划分职责边界,而不是强行让异步线程“继承”事务。

















