案例
update product set name = ‘GTS’ where name = ‘TXC’;
一阶段(准备)
- 解析业务SQL,得到 SQL的类型(UPDATE),表(product),条件(where name = ‘TXC’)等相关的信息
- 查询前镜像,根据解析得到的条件信息,生成查询语句(select id, name, since from product where name = ‘TXC’),定位数据,得到前镜像
- 执行业务SQL,更新这条记录的name为 ‘GTS’
- 查询后镜像,根据前镜像的结果,通过主键定位数据(select id, name, since from product where id = 1),得到后镜像
- 插入回滚日志,把前后镜像数据以及业务SQL相关的信息组成一条回滚日志记录,插入到UNDO_LOG表中
- 向TC注册分支,申请product表中主键值等于 1 的记录的全局锁
- 本地事务提交,业务数据的更新和前面步骤中生成的UNDO LOG一并提交
- 将本地事务提交的结果上报给 TC。
二阶段(提交)
- 收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC
- 异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录
二阶段(回滚)
- 收到TC的分支回滚请求,开启一个本地事务,执行如下操作
- 通过XID和Branch ID查找到相应的UNDO LOG记录
- 数据校验,拿UNDO LOG中的后镜像与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改。这种情况,需要根据配置策略来做处理
- 根据UNDO LOG中的前镜像和业务SQL的相关信息生成并执行回滚的语句(update product set name = ‘TXC’ where id = 1)
- 提交本地事务,并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC