(1). AT模式(一阶段之提交)

  1. 首先,在对某条数据进行操作之前(INSERT/DELETE/UPDATE),先查询出这条数据(INSERT除外),我们称该操作为:镜像之前数据.
  2. 然后,执行业务SQL操作.
  3. 再次,查询这条数据,我们称该操作为:镜像之后数据.
  4. 向TC(事务协调器)申请对这条数据的全局锁(BranchID/XID),注意:此时实际是把数据行的锁交给了TC进行了管理(控制并发).
  5. 把镜像前的数据和镜像后的数据插入到:UNDO_LOG表中(BranchID/XID/undoItems…).
  6. 将结果向TC汇报.
  7. 留个疑问:Seata的隔离级别,默认是读未提交,那上面(第1步和第3步)的查询语句是否带FOR UPDATE?如果不带,是否会有脏读的可能性?
  8. 答案:在这个类:(io.seata.rm.datasource.exec.UpdateExecutor),beforeImage生成的SQL语句时是有带FOR UPDATE,上面的问题就迎刃而解,beforeImage会Lock这些数据行,直到本地commit或rollback(其它线程只能排队).

(2). AT模式(二阶段之回滚)

  1. 收到TC(事务协调器)的Rollback请求,开启一个本地事务.
  2. 通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录.
  3. 数据校验:拿 UNDO LOG 中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改.
  4. 根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句.
  5. 提交本地事务.并把本地事务的执行结果(即分支事务回滚的结果)上报给TC.

(3). AT模式(二阶段之提交)

  1. 收到TC(事务协调器)的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给TC(事务协调器).
  2. 通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录,并删除这条数据.

(4). AT模式缺点

该模式的优点,我就不说了,但是,缺点我需要说一下(因为,阿里对缺陷一点都没有提及):

  1. AT模式下,默认的数据库隔离级别是:读取未提交,所以:开发人员在开发的时候,要特别注意这一点,对开发的培训自然要非常到位.否则会出现脏读和脏写.
  2. AT模式的底层是以(DataSource)为切入点,如果,是多语言协同开发平台(Java/Go/NodeJS…),这应该是最大的不足.