1. 多数据源事务的典型场景
想象你正在开发一个电商平台的支付系统。当用户下单时,你需要同时操作两个数据库:订单库记录订单状态,用户库扣除账户余额。这两个操作必须同时成功或同时失败——这就是典型的多数据源事务场景。我在去年重构物流系统时就遇到过类似需求,当时用原生Spring事务注解调试了整整两天才发现问题所在。
Spring Boot默认的@Transactional注解在单数据源场景下工作良好,但遇到多数据源时就力不从心了。比如下面这段看似正常的代码:
java复制@Transactional
public void placeOrder(Order order) {
orderRepository.save(order); // 操作订单库
userRepository.deductBalance(order.getUserId(), order.getAmount()); // 操作用户库
// 如果这里抛出异常...
}
当异常发生时,你可能会惊讶地发现:订单库回滚了,但用户库的余额变更却提交了!这是因为@Transactional默认只能管理单个数据源的事务。这时候就需要引入dynamic-datasource框架的@DSTransactional注解来拯救局面了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心注解原理对比
2.1 @Transactional的工作机制
Spring原生的@Transactional本质上是通过AOP代理实现的。当你在方法上添加这个注解时,Spring会做三件事:
- 创建数据库连接并关闭自动提交
- 将连接绑定到当前线程的ThreadLocal
- 方法执行成功后提交,异常时回滚
但关键问题在于:每个数据源都有自己的连接池。当方法内切换数据源时,新数据源的操作会使用新的连接,这就破坏了事务的原子性。我在早期项目中就犯过这个错误,导致对账时发现金额总是对不上。
2.2 @DSTransactional的分布式方案
dynamic-datasource的@DSTransactional采用了完全不同的思路。它底层基于Seata的AT模式实现分布式事务,具体流程如下:
- 事务发起方(TM)向事务协调器(TC)注册全局事务
