跳到主要内容
版本:4.6.0

事务选型指南

用多数据源的人一定会撞上事务问题。这一章不讲「有哪些方案」,而是帮你在 30 秒内选对方案。

先理解一个事实​

Spring 原生事务一旦开启,整个线程后续拿到的都是同一个 Connection。

数据源切换靠的是 ThreadLocal 里的一个 key,而 @Transactional 会把连接绑定到线程上。两者叠加的结果是:事务开启之后,切换注解和手动 push 都不再起作用。

这不是 bug,而是关系型数据库事务模型与「一次调用一个连接」的必然结果。理解了这一点,下面所有方案都好选了。

决策树​

需要事务吗?
└─ 不需要 → 什么都不用做

需要。事务内会切换到别的库吗?
├─ 不会(只有单库读写)→ 用 Spring 原生 @Transactional(配合 @DS)
│
└─ 会
├─ 同一个应用进程内 → 用 @DSTransactional
└─ 跨服务/跨进程 → 用 Seata(AT 或 XA)

方案对比​

方案适用场景外部依赖跨服务一致性
@Transactional + @DS事务内不切库的单库事务无否强一致(数据库保证)
@DSTransactional单体应用内跨多个库无否尽力而为(见下方说明)
Seata AT微服务跨服务Seata Server是最终一致,自动补偿
Seata XA跨服务且要求强一致Seata Server是强一致,性能较低
Atomikos XA单进程内需要标准 XAAtomikos否强一致
@DSTransactional 不是严格的 2PC

@DSTransactional 的做法是:为涉及的每个库各开一个本地事务,全部挂在同一个 XID 下,业务方法正常返回时逐库提交,抛异常时逐库回滚。

回滚是尽力而为的——某个库回滚失败不会阻止其他库回滚。提交同样是逐个进行的——如果某个库在 commit 阶段失败,先前已经提交的库无法再回滚。

所以它适合「单体应用内、跨库一致性要求不是 100% 苛刻」的场景。金融级强一致请上 XA。

本章内容​

相关阅读​