XA,2PC,two-phase commit protocol,两阶段事务提交采⽤的是 X/OPEN 组织定义的DTP 模型所抽象的:

  • AP
    应用程序,Application Program,定义事务边界(即定义事务的开始和结束),并且在事务边界内对资源进行操作
  • TM(事务管理器)
    Transaction Manager,负责分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚等
  • RM(资源管理器)
    Resource Manager,如数据库、文件系统等,并提供访问资源的方式

XA 接口

xa_start :负责开启或者恢复一个事务分支
xa_end: 负责取消当前线程与事务分支的关联
xa_prepare:询问 RM 是否准备好提交事务分支
xa_commit:通知 RM 提交事务分支
xa_rollback: 通知 RM 回滚事务分支
xa_recover : 需要恢复的 XA 事务

保证分布式事务的强⼀致性。其中 TM 与 RM 间采⽤ XA 协议进⾏双向通信。
XA 整体设计思路可概括为:在现有事务模型基础上微调扩展而实现的分布式事务。

与传统的本地事务相⽐,XA 事务增加了准备阶段,数据库除了被动接受提交指令外,还可以反向通知调⽤⽅事务是否可以被提交。TM 可以收集所有分⽀事务的准备结果,并于最后进⾏原⼦提交,以保证事务的强⼀致性

  • 两阶段提交模型

Java 通过定义 JTA 接口实现了 XA 模型

JTA 接口中的 ResourceManager 需要数据库⼚商提供 XA 驱动实现,TransactionManager 则需要事务管理器的⼚商实现,传统的事务管理器需要同应⽤服务器绑定,因此使⽤的成本很⾼。而嵌⼊式的事务管器可以以 jar 包的形式提供服务,同 Apache ShardingSphere集成后,可保证分⽚后跨库事务强⼀致性。通常,只有使⽤了事务管理器⼚商所提供的 XA 事务连接池,才能⽀持 XA 的事务。Apache ShardingSphere在整合 XA 事务时,采⽤分离 XA 事务管理和连接池管理的⽅式,做到对应⽤程序的零侵⼊。

MySQL 从5.0.3开始支持 InnoDB 引擎的 XA 分布式事务,MySQL Connector/J 从5.0.0版本开始支持 XA。
在 DTP 模型中,MySQL 属于资源管理器(RM)。分布式事务中存在多个 RM,由事务管理器 TM 来统一进行协调。

MySQL 的 XA

  • XA {START | BEGIN} xid [JOIN | RESUME]
    开启XA事务,如果使用的是XA START而非XA BEGIN,那么不支持[JOIN | RESUME],xid是个唯一值,表示事务分支标
    全局 + 分支 id

  • XA END xid [SUSPEND [FOR MIGRATE]]
    结束一个xA事务,不支持[SUSPEND [FOR MIGRATE]]

  • XA PREPARE xid

    准备提交

  • XA COMIT xid [ONE PHASE]
    提交,如果使用了 ONE PHASE,贼表示使用一阶段提交。两阶段提交协议中,如果只有一个 RM 参与,那么可以优化为一阶段提交

  • XA ROLLBACK xid

    回滚

  • XA recover[convert xid]

列出所有处于 prepare 阶段的 XA 事务

mysql> select * from t;
+----+------+------+
| id | c    | d    |
+----+------+------+
|  0 |    0 |    0 |
|  5 |    5 |    5 |
| 10 |   10 |   10 |
| 15 |   15 |   15 |
| 20 |   20 |   20 |
| 25 |   25 |   25 |
| 30 |   10 |   30 |
+----+------+------+
7 rows in set (0.01 sec)mysql> xa start 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> insert into t values(1,2,3);
Query OK, 1 row affected (0.01 sec)mysql> update t set id = 11 where id = 10;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> xa end 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> xa prepare 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> xa commit 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> select * from t;
+----+------+------+
| id | c    | d    |
+----+------+------+
|  0 |    0 |    0 |
|  1 |    2 |    3 | # 添加的记录
|  5 |    5 |    5 |
| 11 |   10 |   10 | # 修改的记录
| 15 |   15 |   15 |
| 20 |   20 |   20 |
| 25 |   25 |   25 |
| 30 |   10 |   30 |
+----+------+------+
8 rows in set (0.01 sec)mysql> xa start 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> insert into t values(2,5,8);
Query OK, 1 row affected (0.00 sec)mysql> xa end 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> xa prepare 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> xa recover;
# gtr 全局事务 id
# bq 分支事务 id,这就能区分是大事务,还是小事务
+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
|        1 |            3 |            0 | x01  |
+----------+--------------+--------------+------+
1 row in set (0.00 sec)mysql> xa start 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> insert into t values(2,5,8);
Query OK, 1 row affected (0.00 sec)mysql> xa end 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> xa prepare 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> xa recover;
+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
|        1 |            3 |            0 | x01  |
+----------+--------------+--------------+------+
1 row in set (0.00 sec)mysql> xa rollback 'x01';
Query OK, 0 rows affected (0.00 sec)mysql> select * from t;
+----+------+------+
| id | c    | d    |
+----+------+------+
|  0 |    0 |    0 |
|  1 |    2 |    3 |
|  5 |    5 |    5 |
| 11 |   10 |   10 |
| 15 |   15 |   15 |
| 20 |   20 |   20 |
| 25 |   25 |   25 |
| 30 |   10 |   30 |
+----+------+------+
8 rows in set (0.00 sec)

实践分支事务 id

mysql> xa start 'x01', 'b01';
Query OK, 0 rows affected (0.00 sec)mysql> select * from t;
+----+------+------+
| id | c    | d    |
+----+------+------+
|  0 |    0 |    0 |
|  1 |    2 |    3 |
|  5 |    5 |    5 |
| 11 |   10 |   10 |
| 15 |   15 |   15 |
| 20 |   20 |   20 |
| 25 |   25 |   25 |
| 30 |   10 |   30 |
+----+------+------+
8 rows in set (0.00 sec)mysql> insert into t values(2,5,8);
Query OK, 1 row affected (0.00 sec)mysql> select * from t;
+----+------+------+
| id | c    | d    |
+----+------+------+
|  0 |    0 |    0 |
|  1 |    2 |    3 |
|  2 |    5 |    8 |
|  5 |    5 |    5 |
| 11 |   10 |   10 |
| 15 |   15 |   15 |
| 20 |   20 |   20 |
| 25 |   25 |   25 |
| 30 |   10 |   30 |
+----+------+------+
9 rows in set (0.00 sec)mysql> xa end 'x01', 'b01';
Query OK, 0 rows affected (0.00 sec)mysql> xa prepare 'x01', 'b01';
Query OK, 0 rows affected (0.01 sec)mysql> xa recover;
+----------+--------------+--------------+--------+
| formatID | gtrid_length  | bqual_length | data   |
+----------+--------------+--------------+--------+
|        1 |            3 |            3 | x01b01 |
+----------+--------------+--------------+--------+
1 row in set (0.01 sec)
# gtrid_length 全局事务 id 的长度
# bqual_length 分支事务 id 的长度mysql> xa commit 'x01', 'b01';
Query OK, 0 rows affected (0.00 sec)mysql> xa recover;
Empty set (0.00 sec)mysql> select * from t;
+----+------+------+
| id | c    | d    |
+----+------+------+
|  0 |    0 |    0 |
|  1 |    2 |    3 |
|  2 |    5 |    8 |
|  5 |    5 |    5 |
| 11 |   10 |   10 |
| 15 |   15 |   15 |
| 20 |   20 |   20 |
| 25 |   25 |   25 |
| 30 |   10 |   30 |
+----+------+------+
9 rows in set (0.00 sec)
  • MySQL XA事务状态
    ACTIVE状态的XA事务,我们可以执行构成事务的SQL语句,然后发布一个XA END语句。XA END把事务放入IDLE状态。

    XA事务和非XA事务(即本地事务)是互斥的。
    例如,已经执行了 XA START 开启一个XA事务,则本地事务不会被启动,直到XA事务已被提交或被回滚为止。相反的,若已使用START TRANSACTION启动一个本地事务,则XA语句不能被使用,直到该事务被提交或被回滚为止。

时序图

  • 完整的 XA 事务处理时序图
  • 单个 MySQL 的内部操作

XA 过程中,事务失败怎么办?

业务 SQL 执行过程,某个 RM 崩溃怎么处理,全部 prepare 后,某个 RM 崩溃怎么处理,commit 时,某个 RM 崩溃怎么办?

MySQL < 5.7的bug
  • 已经prepare的事务, 在客户端退出或者服务宕机的时候,2PC的事务 会被回滚。
  • 在服务器故障重启提交后, 相应的Binlog被丢失

MySQL 5.6版本在客户端退出的时候,自动把已经prepare的事务回滚了 ,那么MySQL为什么要这样做?这主要取决于MySQL的内部实现,MySQL 5.7以前的版本,对于prepare的事务,MySQL 是不会记录binlog的(官方说是减少fsync, 起到了优化的作用)。只有当分布式事务提交的时候才会把前面的操作写入binlog信息,所以对于binlog来说,分布式事务与普通的事务没有区别,而prepare以
前的操作信息都保存在连接的I0 CACHE中,如果这个时候客户端退出了,以前的binlog信息都会被丢失,再次重连后允许提交的话,
会造成Binlog丢失,从而造成主从数据的不一致,所以官方在客户端退出的时候直接把已经prepare的事务都回滚了!

MySQL > 5.7版本的优化

https://dev.mysql.com/worklog/task/?id=6860,MySQL对于分布式事务,在prepare的时候就完成了写Binlog的操作,通过新增一种叫XA _prepare_ log_ event的event类型来实现,这与以前版本的主要区别(以前版本prepare时不写Binlog)。

事务管理器,负责协调多个数据库(资源管理器)的事务。

  1. 事务管理器先问各个DB:预提交 ok 吗?
  2. 如果每个数据库都回复ok,即预提交成功,开始正式提交事务,在各DB开始执行操作,这里失败会有失败异常重试,日志分析,人工重试。

X/Open,即现在的open group,是一个独立的组织,主要负责制定各种行
业技术标准。X/Open组织主要由各大知名公司或厂商支持,这些组织不光遵循X/Open组织定义的行业技术标准,也参与到标准的制定。

故障分析

单点故障

协调者出错,事务会失败。

集群部署即可。

阻塞资源

占用数据库连接,性能低。

保持连接是为了第一阶段和第二阶段使用的是同一个事务,确保提交或回滚事务,只需将操作前、后的数据落库记录,就能将当前的连接放弃了。
将连接释放掉,就能保证系统的性能了。

提交阶段什么都不用做,因为数据库已有操作后记录。
回滚也可以,因为已经记录过操作前的记录。

数据不一致

二阶段出错,数据不一致

适用场景

适合单块应用中,跨多库的分布式事务,而且因其严重依赖DB层面解决事务,所以效率很低,不适合高并发场景。

互联网公司基本都不用,因某个系统内部如果出现跨多库的操作,是不合规的。现在的微服务,一个大的系统分成几十甚至上百个服务。一般规约每个服务只能操作自己对应的一个数据库。

如果你要操作别的服务对应的库,不允许直连别的服务的库。要操作别人的服务的库,必须通过调用别的服务的接口

主流的开源XA分布式事务解决方案

Element ATOMIKOS narayanna seata
TM 去中心化设计,性能较高 去中心化设计,性能较高 中心化设计,性能较差,bug 多
日志存储件 只支持文件 文件、数据库 文件、数据库
扩展性 较好 一般 一般
事务恢复 只支持单机事务恢复 集群模式恢复 问题很多,未能正确恢复
XA 标准 XA 实现 标准 XA 实现 非标准的 XA 实现

分布式事务实战---XA两阶段提交(2PC)方案详解相关推荐

  1. oracle二阶段事物,分布式事务 两阶段提交 (2PC)

    两阶段提交(2PC) 是 Oracle Tuxedo 系统提出的 XA 分布式事务协议的其中一种实现方式. XA协议中有两个重要角色:事务协调者和事务参与者 既然叫两阶段提交,肯定是分为两个阶段. J ...

  2. CAP原理,分布式一致性算法,两阶段提交,三阶段提交,Paxos,Raft,zookeeper的选主过程,zab协议,顺序一致性,数据写入流程,节点状态,节点的角色

    我们知道,一般在分布式应用都有CAP准则: C Consistency, 一致性,分布式中的各个节点数据保持一致 A availability 可用性,任何时刻,分布式集群总是能够提供服务 P par ...

  3. 分布式事务:TCC两阶段异步补偿型

    点击上方"田守枝的技术博客",关注我 提示:可能有人在公众号上看过这篇文章,这是我2018年2月份在我的博客上写的文章,现在搬到公众号上来,搬上来之前已经被其他公众号抄袭了,懒的投 ...

  4. mongodb mysql 事务_MongoDB数据库两阶段提交实现事务的方法详解 _ 蚂蚁视界

    本文实例讲述了MongoDB数据库两阶段提交实现事务的办法.分享给年夜家供年夜家参考,详细如下: MongoDB数据库中操作单个文档老是原子性的,然而,涉及多个文档的操作,通常被作为一个"事 ...

  5. 学习笔记-------两阶段提交 2PC

  6. 目标检测之两阶段算法--Fast R-CNN详解

    论文题目:<Fast R-CNN> 论文地址:Fast R-CNN 1. 概述 之所以提出Fast R-CNN,主要是因为R-CNN存在以下几个问题:1.训练分多步.通过上一篇博文我们知道 ...

  7. 自动驾驶感知算法实战11——多传感器融合感知方案详解

    自动驾驶感知算法实战专栏:https://blog.csdn.net/charmve/category_12097938.html 目录 1 何为多传感器融合? 2 多传感器融合的优势 3. 多传感器 ...

  8. 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究[转]

    1.XA XA是由X/Open组织提出的分布式事务的规范.XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接 ...

  9. 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究

    本文原文连接: http://blog.csdn.net/bluishglc/article/details/7612811 ,转载请注明出处! 1.XA XA是由X/Open组织提出的分布式事务的规 ...

最新文章

  1. 程序员,唯有锻炼与读书不能辜负
  2. Windows Server 2016第三个技术预览版新技术
  3. alt+数字 符号大全_【BIM工具箱】Revit中特殊符号大全和输入技巧
  4. Index of c#
  5. Launcher(待完善...)
  6. 站点分析基础概念之目标转化率
  7. 正交试验设计例题及答案_正交表测试用例设计方法的特点是什么?
  8. notion自建服务器,最详细的NOTION功能模块列表
  9. 《工业元宇宙白皮书 2022年 》(附免费pdf下载地址)
  10. android word 转pdf插件下载,word转pdf转换器
  11. SSM基于小程序的医院预约挂号系统 毕业设计-附源码260839
  12. 排队问题解题思路_有关排队问题的排列组合题解法举例
  13. 前端新技术(离线缓存、CDN内容分发网络)
  14. 51单片机学习笔记——SH88F4051A
  15. 全面提升转化率和客单价的方法和技巧
  16. 【工具DIY】DIY一个高精度电阻箱
  17. 2023年4月国产数据库大事记-墨天轮
  18. 1、新建基于标准固件库MDK5工程模板(STM32F103ZET6)
  19. tmail邮箱服务器,邮件服务器(一)Sendmail服务器1
  20. TeeChart 商业版 [2022.4.8] TeeChart.NET 专业版

热门文章

  1. uniapp本地存储和本地储存取值
  2. 轩辕传奇服务器合并信息,4月28日部分服务器数据互通公告
  3. datahub文档_阿里云DataHub基本了解
  4. 幼儿园调查过程怎么写_如何观察?如何分析和记录?幼儿园观察记录应该怎么写?...
  5. GBase 8a Kafka 数据同步
  6. 软考高级系统架构设计师备考攻略
  7. 扭蛋是什么?我来告诉你
  8. vue cli更换版本
  9. java多线程的应用-使用两个线程打印12A34B56C78D
  10. 个人情感Emotion