文章目录
- [seata AT的工作机制](#seata AT的工作机制)
- 一.通过SPI来加载配置SeataAutoConfiguration
- 二.创建全局事务扫描类GlobalTransactionScanner
- [三.代理spring 的相关bean](#三.代理spring 的相关bean)
- 四.初始化TM和RM
- 五执行拦截
- 六.执行全局事务
- 七.写入Undo和提交的过程
参考视频
代码的版本为1.4.2
seata AT的工作机制
一阶段
- 解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where name = 'TXC')等相关的信息。
- 查询前镜像:根据解析得到的条件信息,生成查询语句(更新前的数据)
- 执行业务 SQL
- 查询后镜像(更新后的数据)
- 把前后的数据拼接成一个记录插入UNDO_LOG 中
- 获取主键的全局锁
- 本地事务提交
- 将本地事务提交的结果上报给 TC
二阶段-提交
- 收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。
- 异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。
二阶段-回滚
- 收到 TC 的分支回滚请求,开启一个本地事务
- 通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录
- 数据校验:拿 UNDO LOG 中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改,需要根据配置策略来做处理
- 根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句
- 提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC
一.通过SPI来加载配置SeataAutoConfiguration

二.创建全局事务扫描类GlobalTransactionScanner

三.代理spring 的相关bean
GlobalTransactionScanner继承了AbstractAutoProxyCreator(aop 代理类)
重写了wrapIfNecessary代理方法

GlobalTransactionScanner实现了InitializingBean方法。
四.初始化TM和RM

五执行拦截
GlobalTransactionalInterceptor调用invoke方法

六.执行全局事务
io.seata.spring.annotation.GlobalTransactionalInterceptor#handleGlobalTransaction
查看io.seata.tm.api.TransactionalTemplate#execute
1.得到事务信息
1.1 获取当前事务,主要是获取XID
1.2根据配置的不同的传播行为,执行不同的逻辑
1.3 当前没有事务,则新建一个事务
2.开启全局事务
执行业务逻辑
3.如果有异常就回滚,通过undo_log表进行补偿
4.如果没有异常就全局提交
5.释放资源

流程如下

七.写入Undo和提交的过程
SPI来加载配置SeataDataSourceAutoConfiguration
使用DataSourceProxy来代理应用的数据源信息,启动一个线程定时的获取表信息

在执行sql的时候,创建的createStatement
io.seata.rm.datasource.AbstractConnectionProxy#createStatement()

都是执行的
io.seata.rm.datasource.exec.ExecuteTemplate#execute方法

进入executor.execute(args)后
io.seata.rm.datasource.exec.AbstractDMLBaseExecutor#doExecute
如果是自动提交,则改为手动提交

在执行sql前先获之前的数据

io.seata.rm.datasource.ConnectionProxy#processGlobalTransactionCommit
1.写入undo log
2.执行提交

io.seata.rm.datasource.undo.mysql.MySQLUndoLogManager#insertUndoLog
