4.11.3 什么是XA 事务?

《数据库程序员面试笔试宝典》第4章数据库基础,本章主要介绍数据库基础部分的面试题,比较适合应届毕业生,也适合由其他岗位转数据库岗位的人员。本节为大家介绍什么是XA 事务。

作者:猿媛之家
来源:机械工业出版社|2018-11-09 

4.11.3 什么是XA 事务?

XA(eXtended Architecture)是指由X/Open 组织提出的分布式交易处理的规范。XA 是一个分布式事务协议,由Tuxedo 提出,所以分布式事务也称为XA 事务XA 协议主要定义了事务管理器TM(Transaction Manager,协调者)和资源管理器RM(Resource Manager,参与者)之间的接口。其中,资源管理器往往由数据库实现,如Oracle、DB2、MySQL,这些商业数据库都实现了XA 接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。XA 事务是基于两阶段提交(Two-phaseCommit,2PC)协议实现的,可以保证数据的强一致性,许多分布式关系型数据管理系统都采用此协议来完成分布式。阶段一为准备阶段,即所有的参与者准备执行事务并锁住需要的资源。当参与者Ready时,向TM 汇报自己已经准备好。阶段二为提交阶段。当TM 确认所有参与者都Ready 后,向所有参与者发送COMMIT 命令。

XA 事务允许不同数据库的分布式事务,只要参与在全局事务中的每个结点都支持XA 事务。Oracle、MySQL 和SQL Server 都支持XA 事务。

XA 事务由一个或多个资源管理器(RM)、一个事务管理器(TM)和一个应用程序(ApplicationProgram)组成。

资源管理器:提供访问事务资源的方法。通常一个数据库就是一个资源管理器。

事务管理器:协调参与全局事务中的各个事务。需要和参与全局事务的所有资源管理器进行通信。

应用程序:定义事务的边界。

XA 事务的缺点是性能不好且无法满足高并发场景。一个数据库的事务和多个数据库间的XA 事务性能会相差很多。因此,要尽量避免XA 事务,如可以将数据写入本地,用高性能的消息系统分发数据,或使用数据库复制等技术。只有在其他办法都无法实现业务需求,且性能不是瓶颈时才使用XA。

X/Open DTP模型(1994)包括应用程序(AP)、事务管理器(TM)、资源管理器(RM)、通信资源管理器(CRM)四部分。

在这个模型中,通常事务管理器(TM)是交易中间件,资源管理器(RM)是数据库,通信资源管理器(CRM)是消息中间件

一般情况下,某一数据库无法知道其它数据库在做什么,因此,在一个DTP环境中,交易中间件是必需的,由它通知和协调相关数据库的提交或回滚。而一个数据库只将其自己所做的操作(可恢复)影射到全局事务中。

XA就是X/Open DTP定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等

https://www.jianshu.com/p/c2d8f2bbcb6f

MySQL分布式事务操作

1. MySQL XA事务的语法

主要有:

# 在mysql实例中开启一个XA事务,指定一个全局唯一标识;

mysql> XA START 'any_unique_id';

# XA事务的操作结束;

mysql> XA END 'any_unique_id ';

# 告知mysql准备提交这个xa事务;

mysql> XA PREPARE 'any_unique_id';

# 告知mysql提交这个xa事务;

mysql> XA COMMIT 'any_unique_id';

# 告知mysql回滚这个xa事务;

mysql> XA ROLLBACK 'any_unique_id';

# 查看本机mysql目前有哪些xa事务处于prepare状态;

mysql> XA RECOVER;

2. XA事务恢复

如果执行分布式事务的mysql crash了,MySQL按照如下逻辑进行恢复:

a. 如果这个xa事务commit了,那么什么也不用做。

b. 如果这个xa事务还没有prepare,那么直接回滚它。

c. 如果这个xa事务prepare了,还没commit, 那么把它恢复到prepare的状态,由用户去决定commit或rollback。

当mysql crash后重新启动之后,执行“XA RECOVER;”查看当前处于prepare状态的xa事务,然后commit或rollback它们。

MySQL分布式事务限制

a. XA事务和本地事务以及锁表操作是互斥的

开启了xa事务就无法使用本地事务和锁表操作

mysql> xa start 't1xa';

Query OK, 0 rows affected (0.04 sec)

mysql> begin;

ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in theACTIVE state

mysql> lock table t read;

ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in theACTIVE state

开启了本地事务就无法使用xa事务

mysql> begin;

Query OK, 0 rows affected (0.00 sec)

mysql> xa start 'rrrr';

ERROR 1400 (XAE09): XAER_OUTSIDE: Some work is done outside global transaction

b. xa start之后必须xa end,否则不能执行xa commit和xa rollback

所以如果在执行xa事务过程中有语句出错了,你也需要先xa end一下,然后才能xa rollback。

mysql> xa start 'tt';

Query OK, 0 rows affected (0.00 sec)

mysql> xa rollback 'tt';

ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the  ACTIVE state

mysql> xa end 'tt';

Query OK, 0 rows affected (0.00 sec)

mysql> xa rollback 'tt';

Query OK, 0 rows affected (0.00 sec)

MySQL 5.7对分布式事务的支持

一直以来,MySQL数据库是支持分布式事务的,但是只能说是有限的支持,具体表现在:

已经prepare的事务,在客户端退出或者服务宕机的时候,2PC的事务会被回滚。

在服务器故障重启提交后,相应的Binlog被丢失。

上述问题存在于MySQL数据库长达数十年的时间,直到MySQL-5.7.7版本,官方才修复了该问题。下面将会详细介绍下该问题的具体表现和官方修复方法,这里分别采用官方MySQL-5.6.27版本(未修复)和MySQL-5.7.9版本(已修复)进行验证。

先来看下存在的问题,我们先创建一个表如下:

CREATE TABLE t(

id INT AUTO_INCREMENT PRIMARY KEY,

a INT

)ENGINE=InnoDB;

对于上述表,通过如下操作进行数据插入:

mysql> XA START 'mysql56';

mysql> INSERT INTO t VALUES(1,1);

mysql> XA END 'mysql56';

mysql> XA PREPARE 'mysql56';

通过上面的操作,用户创建了一个分布式事务,并且prepare没有返回错误,说明该分布式事务可以被提交。通过命令XA RECOVER查看显示如下结果:

mysql> XA RECOVER;

+----------+--------------+--------------+---------+

| formatID | gtrid_length | bqual_length | data  |

+----------+--------------+--------------+---------+

| 1    | 7      | 0      | mysql56 |

+----------+--------------+--------------+---------+

若这时候用户退出客户端后重连,通过命令xa recover会发现刚才创建的2PC事务不见了。即prepare成功的事务丢失了,不符合2PC协议规范!!!

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

官方的做法,貌似干得很漂亮,牺牲了一点标准化的东西,至少保证了主从数据的一致性。但其实不然,若用户已经prepare后在客户端退出之前,MySQL发生了宕机,这个时候又会怎样?

MySQL在某个分布式事务prepare成功后宕机,宕机前操作该事务的连接并没有断开,这个时候已经prepare的事务并不会被回滚,所以在MySQL重新启动后,引擎层通过recover机制能恢复该事务。当然该事务的Binlog已经在宕机过程中被丢失,这个时候,如果去提交,则会造成主从数据的不一致,即提交没有记录Binlog,从上丢失该条数据。所以对于这种情况,官方一般建议直接回滚已经prepare的事务。

以上是MySQL 5.7以前版本MySQL在分布式事务上的各种问题,那么MySQL 5.7版本官方做了哪些改进?这个可以从官方的WL#6860描述上得到一些信息,我们还是本着没有实践就没有发言权的态度,从具体的操作上来分析下MySQL 5.7的改进方法。还是以上面同样的表结构进行同样的操作如下:

mysql> XA START 'mysql57';

mysql> INSERT INTO t VALUES(1,1);

mysql> XA END 'mysql57';

mysql> XA PREPARE 'mysql57'

这个时候,我们通过mysqlbinlog来查看下Master上的Binlog,结果如下:

 

同时也对比下Slave上的Relay log,如下:

 

通过上面的操作,明显发现在prepare以后,从XA START到XA PREPARE之间的操作都被记录到了Master的Binlog中,然后通过复制关系传到了Slave上。也就是说MySQL 5.7开始,MySQL对于分布式事务,在prepare的时候就完成了写Binlog的操作,通过新增一种叫XA_prepare_log_event的event类型来实现,这是与以前版本的主要区别(以前版本prepare时不写Binlog)。

当然仅靠这一点是不够的,因为我们知道Slave通过SQL thread来回放Relay log信息,由于prepare的事务能阻塞整个session,而回放的SQL thread只有一个(不考虑并行回放),那么SQL thread会不会因为被分布式事务的prepare阶段所阻塞,从而造成整个SQL thread回放出现问题?这也正是官方要解决的第二个问题:怎么样能使SQL thread在回放到分布式事务的prepare阶段时,不阻塞后面event的回放?其实这个实现也很简单(在xa.cc::applier_reset_xa_trans),只要在SQL thread回放到prepare的时候,进行类似于客户端断开连接的处理即可(把相关cache与SQL thread的连接句柄脱离)。最后在Slave服务器上,用户通过命令XA RECOVER可以查到如下信息:

mysql> XA RECOVER;

+----------+--------------+--------------+---------+

| formatID | gtrid_length | bqual_length | data  |

+----------+--------------+--------------+---------+

| 1    | 7      | 0      | mysql57 |

+----------+--------------+--------------+---------+

至于上面的事务什么时候提交,一般等到Master上进行XA COMMIT  ‘mysql57’后,slave上也同时会被提交。

总结

综上所述,MySQL 5.7对于分布式事务的支持变得完美了,一个长达数十年的bug又被修复了,因而又多了一个升级到MySQL 5.7版本的理由。

XA 事务的更多相关文章

  1. 什么是XA事务

    什么是XA事务 分布式事务处理是指一个事务可能涉及多个数据库操作分布式事务处理的关键是必须有一种方法可以知道事务在任何地方所做的所有动作,提交或回滚事务必须产生一致的结果(全部提交或全部回滚). XA ...

  2. XA: 事务和两阶段提交

    本文原文连接:http://blog.csdn.net/bluishglc/article/details/7612811 ,转载请注明出处! 1.XA XA是由X/Open组织提出的两阶段提交协议, ...

  3. XA事务与MySQL

    XA事务就是两阶段提交的一种实现方式 XA规范主要定义了事务管理器TM,和资源管理器RM之间的接口 根据2PC的规范,将一次事务分割成两个阶段 1. prepare阶段 TM向所有RM发送prepar ...

  4. ## 【分布式事务】面试官问我:MySQL中的XA事务崩溃了如何恢复??

    写在前面 前段时间搭建了一套MySQL分布式数据库集群,数据库节点有12个,用来测试各种分布式事务方案的性能和优缺点.测试MySQL XA事务时,正当测试脚本向数据库中批量插入数据时,强制服务器断电! ...

  5. 当MySQL执行XA事务时遭遇崩溃,且看华为云如何保障数据一致性

    摘要:当前MySQL所有版本不支持分布式事务的崩溃恢复安全,这严重影响了分布式事务的高可用保障. 华为云数据库内核高级技术专家,拥有十多年MySQL内核研发经验,目前在华为云数据库团队研发华为云数据库 ...

  6. MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】

    概念: XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口.XA为了实现分布 ...

  7. MySQL数据库分布式事务XA优缺点与改进方案

    1 MySQL 外部XA分析 1.1 作用分析 MySQL数据库外部XA可以用在分布式数据库代理层,实现对MySQL数据库的分布式事务支持,例如开源的代理工具:ameoba[4],网易的DDB,淘宝的 ...

  8. 如何实现XA式、非XA式Spring分布式事务

    Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...

  9. 非XA式Spring分布式事务

    Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...

随机推荐

  1. todolist 包含本地存储知识

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. centos 6.5安装zabbix 4.4

    一.安装环境 本环境,使用单机部署. 操作系统:centos 7.5 x64zabbix-server,Mysql,php,nginx都在同一台服务器.都是使用Yum安装的! 官方安装文档: http ...

  3. 【题解】Luogu P5283 [十二省联考2019]异或粽子

    原题传送门 看见一段的异或和不难想到要做异或前缀和\(s\) 我们便将问题转化成:给定\(n\)个数,求异或值最靠前的\(k\)对之和 我们珂以建一个可持久化01trie,这样我们就珂以求出每个值\( ...

  4. c# 结构体实现数据新增(数据字段较多的情况使用) 一

    点击新增按钮 { ChkFormIDBox.Text = Coeno.DevChk.DevChk.CleanUpInput(ChkFormIDBox.Text);  --清除表单文本框数据输入 if ...

  5. JavaScript之控制标签属性

    var pic=document.getElementById('pic'); var obtn=document.getElementById('btn'); console.log(pic.get ...

  6. 在Controller中添加事务管理

    文章参考了此博客: https://blog.csdn.net/qq_40594137/article/details/82772545 写这篇文章之前先说明一下: 1. Controller中添加事 ...

  7. JavaScript笔记02_对象

    目录 1. 函数 1. 函数创建 2. 函数的参数 2. return.break.continue 3. 立即执行函数 4. 对象 5. 枚举对象中的属性 6. 声明提前 1.变量的声明提前 2. ...

  8. 有趣for循环

    String fileValue = "2;3;4;5;6;"; String[] arry = fileValue.split(";"); for (int ...

  9. maven学习笔记二(了解maven的基本命令)

    maven常用的命令 mvn archetype:create 创建Maven项目 mvn compile 编译源代码 mvn deploy 发布项目 mvn test-compile 编译测试源代码 ...

  10. 交换机 VLAN 的划分

    交换机怎么划分VLAN?本次的实验很简单,就是通过VLAN的划分,使不同VLAN之间无法通信,但是相同VLAN不受影响. 实验拓扑 在一台交换机下连接三台VPC,划分VLAN,地址规划如下: 名称 接 ...