Seata服务端同步提交事务核心源码解析
文章目录
- 前言
- 一、doGlobalCommit(同步提交)
- 2.1、closeAndClean()
- 2.2、changeGlobalStatus
- 2.3、doGlobalCommit
- 2.3.1、findGlobalSession
- 总结
前言
本篇介绍Seata服务端TC如何驱动RM提交事务。
一、doGlobalCommit(同步提交)
doGlobalCommit是提交事务的方法:

首先会根据客户端传递的XID,查找是否存在全局事务,如果不存在,就直接返回客户端Finished,同样地,如果超时,直接返回给客户端TimeoutRollbacking。

添加一个监听器,然后利用SessionManager执行lambda表达式中的逻辑:
- 如果全局事务的状态非Begin,直接返回false。
- 如果全局事务的状态Begin
- 关闭事务,释放全局锁
- 驱动所有的RM提交事务,还要考虑到支持异步提交的场景。

2.1、closeAndClean()
closeAndClean的作用是释放全局锁,如果是AT模式,还需要执行clean的方法:


选择数据库的实现
最终会释放锁 删除lock_table的记录:


根据客户端发送的XID删除,最终会执行如下的SQL:
delete from lock_table where xid = ? ;
2.2、changeGlobalStatus
同步提交的情况下:

最终会走到DataBaseTransactionStoreManager的writeSession的update分支:


**执行如下的sql,更新global_table 的状态为2 **
update global_table set status = ?,gmt_modified = now() where xid = ?;
commit在同步提交的情况下,会走到doGlobalCommit分支:

2.3、doGlobalCommit
在doGlobalCommit方法中,首先会判断,如果当前的模式是SAGA,则走SAGA的这一部分逻辑。否则就是其他模式的提交

首先会执行globalSession.getSortedBranches()方法,获取所有的分支事务信息:

转换了一下源码中的写法,更加清晰易懂一点。

2.3.1、findGlobalSession
最终会调用到DataBaseTransactionStoreManager的readSession:

底层实际上是执行了两条SQL:
-- 查询的是global_table 表中所有的字段,简化成了*
select * from global_table where xid = ?";
-- 查询分支事务表,查出某个主线事务下的所有分支事务
select * from branch_table where xid = 上一条sql查询结果中的xid(主线事务的XID) order by gmt_create asc
最终将当前主线事务下的分支事务,加到branchSessions集合中:

在最外层SessionHelper#forEach中,会去遍历所有的分支事务,

得到当前XID下的所有分支事务后,遍历所有的分支事务,执行lambda表达式中的内容:
如果分支在第一阶段就失败了,说明这个分支没有成功参与事务,因此可以将其从全局事务中移除,并继续下一个。PhaseOne_Failed的状态,是TC 已记录了这个分支(即注册成功),但分支主动上报自己第一阶段失败的结果,如果是因为RM业务发生了异常,则Spring 事务机制自动回滚,Seata 也不会写 undo log,也不会向 TC 汇报任何分支
在branchCommit方法中,TC会驱动每一个RM去提交事务,然后根据RM返回的状态去判断。

- 如果返回的是
PhaseTwo_Committed两阶段提交成功,则执行removeBranch,主要是删除该分支在lock_table的记录,并且删除branch_table的记录,清理branchSessions

- 如果返回的是
PhaseTwo_CommitFailed_Unretryable两阶段提交失败并且无法重试,则将整个全局事务标记为提交失败(Finished + 状态为 CommitFailed),并将其从内存事务会话中清理掉。

最后会进行全局事务的最终处理,删除全局事务信息。

总结
Seata 服务端在同步提交全局事务的过程中,主要完成了以下工作:
- 释放锁,删除
lock_table的记录。 - 将
global_table表中的状态改为2。 - 遍历并驱动所有的分支事务提交(Phase Two 提交),每个分支由 TC 向对应的 RM 发起提交请求。
- 根据各分支事务返回的状态进行处理:
- 若分支返回
PhaseTwo_Committed,表示该分支已成功提交,TC 会调用removeBranch方法:清理内存中的branchSession,并删除该分支在branch_table和lock_table中的记录。 - 若分支返回
PhaseTwo_CommitFailed_Unretryable,表示分支提交失败且不可重试,TC 会将全局事务状态设置为CommitFailed(属于结束状态),并清理内存中的全局事务会话。
- 若分支返回
- 所有分支提交完成后,TC 会将
global_table中该全局事务的状态更新为Committed(提交成功)或CommitFailed(提交失败)。 - 如果全局事务已完成且所有资源已释放,TC 会清理
global_table中对应事务的记录,以完成整个分布式事务的生命周期管理。
