TC (Transaction Coordinator) - 事务协调者
维护全局/分支事务的状态,驱动全局事务的提交与回滚
TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开启、提交、回滚全局事务
RM (Resource Manager) - 资源管理器
管理分支事务(本地事务)与TC交互,注册、报告分支事务状态,管理分支事务的提交、回滚
1、AT
如上图如果使用的是AT模式,需要在每个DB创建一个UNDO_LOG 表,把业务Sql和前后镜像SQL租出一条回滚记录插入该表
整体机制
一阶段:业务数据和回滚日志记录在同一个事务中提交,提交完释放数据库连接,释放本地锁
二阶段:分支事务全部成功,异步提交(删除回滚日志);分支事务有失败,通过一阶段的回滚日志进行补偿
注意点:
1、t1,t2两个线程操作一条数据,t1分支事务提交前会获取全局事务,如果t1不释放全局事务,t2分支事务提交时获取全局锁会等待,直到t1全局事务是否或者t2超时退出
2、AT中每个分支事务都是独立的,只要不更新同一条数据就没什么关系,即便发生更新同一条数据也只会在真正提交的时候等待全局事务,t1,t2几乎是并行的
3、t2一阶段正持有本地锁并且等待获取全局锁;t1第二阶段回滚,需要获取本地锁,这个时候就出现了循环等待的情况(也就是我们常说的死锁条件),这个时候为了避免脏写,需要t2获取全局锁超时,释放本地锁,t1获取到本地锁执行回滚补偿
具体过程
UNDO_LOG
表中。--一条insertproduct
表中,主键值等于 1 的记录的 全局锁 。期间多了两次查询,一条insert语句,比直接更新效率低了不止一倍
2、TCC
1、需要业务编写prepare ,commit,rollback
2、全局管理分支事务,不存在等待,需要自己维护业务逻辑(比如维护一个中间态,扣款的时候先冻结)
3、saga
1、每个业务都需要单独实现数据的正向操作和逆向操作
2、如果分支业务都正常,事务结束;如果分支业务异常,可正向或逆向补偿
4、XA
1、执行业务前先获取全局事务,不存在分支事务情况
2、t1未释放全局事务之前,t2一直等待或者超时
3、最长得等时间=最长的分支RM
AT和XA
1、AT不需要单独配置,XA方式一:要求开发者配置 XADataSource,方式二:根据开发者的普通 DataSource 来创建但需要创建出相应的 XAConnection
2、AT分支事务单独管理释放,XA需要等待每个分支事务都释放(所有的分支事务时间依赖于最长的分支事务)
3、AT需要建UNDO_LOG表记录回滚日志,XA不需要建表
TCC和Saga
1、TCC需要实现三个接口,Saga业务维护状态通过补偿实现一致性
总体来说:
1、TCC,Saga需要业务代码侵入,并且是每个业务都要写一套
2、XA对接简单,并发量支持有限
3、AT如果链路较长,更新频繁,也可能存在等待时间较长
题外话:saga是不是有点像平时写代码不要事务,用job或MQ做最终一致性的样子