AT事务模型使用

发布时间 2024-01-04 16:16:26作者: 周仙僧

机制

两阶段提交协议的演变:

  • 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
  • 二阶段:
    • 提交异步化,非常快速地完成。
    • 回滚通过一阶段的回滚日志进行反向补偿。

集成过程

参考Seata客户端集成

工作机制

一阶段

  1. 根据update语句的条件组成select脚本,查询得到更改前的数据记录;
  2. 执行update语句,更改数据库数据记录;
  3. 根据数据记录的主键,查询得到更改后的数据记录;
  4. 将update语句执行前后的数据记录组装成一条回滚日志记录,插入到 undo_log 表中;
  5. 提交本地事务前,向TC注册分支,并根据修改的数据记录主键申请记录数据表的全局锁;
  6. 提交本地事务,完成业务数据记录和undo_log表的更新;
  7. 将本地事务的提交结果上传给TC。

二阶段-回滚

  1. 收到TC的分支回滚请求,开启一个本地事务;
  2. 通过xid和branch_id查找到相应的undo_log记录;
  3. 数据校验:拿undo_log中的修改后记录与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改,需要根据配置策略来做处理;
  4. 根据undo_log中的前记录和业务SQL的相关信息生成并执行回滚的语句;
  5. 提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。

二阶段-提交

  1. 收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。
  2. 异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。

写隔离(针对同一业务场景的高并发)

  1. 分支事务执行时先读取本地事务锁,全局隔离级别是为“读未提交”(默认)
  2. 执行分支UPDATE命令
  3. 获取全局事务锁
  4. 提交本地事务,释放本地事务锁
    • 成功-提交全局事务、释放全局事务锁
    • 失败-回滚本地事务

图例

  • 成功
  • 失败

读隔离(针对不同业务场景的脏读)

针对 FOR UPDATE 的 SELECT 语句做代理获取全局锁;分支事务在执行时首先通过该语句请求全局锁,获取到全局锁后才开始事务的执行。
例图