MySQL 从5.0.3开始支持XA分布式事务,且只有InnoDB存储引擎支持。MySQL Connector/J 从5.0.0版本之后开始直接提供对XA的支持。

需要注意的是, 在DTP模型中,mysql属于资源管理器(RM)。而一个完整的分布式事务中,一般会存在多个RM,由事务管理器TM来统一进行协调。因此,这里所说的mysql对XA分布式事务的支持,一般指的是单台mysql实例如何执行自己的事务分支。

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

XAENDxid[SUSPEND[FOR MIGRATE]]//结束一个XA事务,不支持[SUSPEND [FOR MIGRATE]]

XA PREPARE xid准备提交

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

XA ROLLBACK xid//回滚

XA RECOVER[CONVERT XID]//列出所有处于PREPARE阶段的XA事务

下面是一个简单的msyql XA事务案例,演示了mysql作为全局事务中的一个事务分支,将一行记录插入到一个表中。

mysql>XA START'xatest’; //其中'xatest’就是xid的值

QueryOK,0rows affected(0.00sec)

mysql>insertintouser(name)values("tianshozuhi");

QueryOK,1row affected(0.00sec)

mysql>XAEND'xatest';

QueryOK,0rows affected(0.00sec)

mysql>XA PREPARE'xatest';

QueryOK,0rows affected(0.01sec)

mysql>XA COMMIT'xatest';

QueryOK,0rows affected(0.01sec)

XA事务的状态,按照如下步骤进行展开

使用XA START来启动一个XA事务,并把它置于ACTIVE状态。

对于一个ACTIVE状态的 XA事务,我们可以执行构成事务的SQL语句,然后发布一个XA END语句。XA END把事务放入IDLE状态。

对于一个IDLE 状态XA事务,可以执行一个XA PREPARE语句或一个XA COMMIT…ONE PHASE语句:

XA PREPARE把事务放入PREPARED状态。

在此点上的XA RECOVER语句将在其输出中包括事务的xid值,因为XA RECOVER会列出处于PREPARED状态的所有XA事务。

XA COMMIT…ONE PHASE用于预备和提交事务。xid值将不会被XA RECOVER列出,因为事务终止。

对于一个PREPARED状态的 XA事务,您可以发布一个XA COMMIT语句来提交和终止事务,或者发布XA ROLLBACK来回滚并终止事务。

针对一个给定的客户端连接而言,XA事务和非XA事务(即本地事务)是互斥的。例如,已经执行了”XA START”命令来开启一个XA事务,则本地事务不会被启动,直到XA事务已经被提交或被 回滚为止。相反的,如果已经使用START TRANSACTION启动一个本地事务,则XA语句不能被使用,直到该事务被提交或被 回滚为止。

最后,如果一个XA事务处于ACTIVE状态,是不能直接进行提交的,如果这样做,mysql会抛出异常:

ERROR1399(XAE07):XAER_RMFAIL:Thecommand cannot be executed

whenglobaltransactionisinthe ACTIVE state

关于XID的说明

mysql中使用xid来作为一个事务分支的标识符。事实上xid作为事务分支标识符是在XA规范中定义的,在<< Distributed Transaction Processing: The XA Specification>> 4.2 节中,规定了一个xid的结构,通过C语言进行描述,如下:

/∗

∗Transactionbranch identification:XIDandNULLXID:

∗/

#defineXIDDATASIZE128/∗sizeinbytes∗/

#defineMAXGTRIDSIZE64/∗maximum sizeinbytes of gtrid∗/

#defineMAXBQUALSIZE64/∗maximum sizeinbytes of bqual∗/

structxid_t{

longformatID;/* format identifier */

longgtrid_length;/* value 1-64 */

longbqual_length;/* value 1-64 */

chardata[XIDDATASIZE];

};

/∗

∗A value of-1informatID means that the XIDisnull.

∗/

typedefstructxid_tXID;

/∗

∗Declarationsof routinesbywhichRMscallTMs:

∗/

externintax_reg(int,XID∗,long);

externintax_unreg(int,long);

XA规范定义了一个xid有4个部分组成:

gtrid:

全局事务标识符(global transaction identifier),最大不能超过64字节

bqual:

分支限定符(branch qualifier),最大不能超过64字节

data:

xid的值,其是 gtrid和bqual拼接后的内容。因为gtrid和bqual最大都是64个字节,因此data的最大长度为128。不过,在xid的结构体中,并没有gtrid和bqual,只有gtrid_length、bqual_length。由于二者的内容都存储在data中,因此我们可以根据data反推出gtrid和bqual。举例来说,假设gtrid为”g12345”(5个字节),bqual为”b456”(4个字节)。那么在构造xid结构体时,gtrid_length=5,bqual_length=4,data=”g12345b456”,那么在反推的时候:

从data[0]到data[gtrid_length-1]之间的部分就是gtrid的值;从data[gtrid_length]到data[gtrid_length+bqual_length-1]部分就是bqual的值。

formatId:

而formatId的作用就是记录gtrid、bqual的格式,类似于memcached中flags字段的作用。XA规范中通过一个结构体约定了xid的组成部分,但是并没有规定data中存储的gtrid、bqual内容到底应该是什么格式。你可以选择使用数字,也可以选择使用字符串,到底选择什么由开发者自行决定,只要最终能保证data中的内容是全局唯一的即可。XA规范建议使用OSI CCR风格来组织xid的内容,此时formatId应该设置为0.

在mysql官方文档中,关于xid的组成也有类似的说明:

xid: gtrid [, bqual [, formatID ]]

其中,bqual、formatID是可选的。解释如下:

gtrid : 是一个全局事务标识符(global transaction identifier),

bqual:是一个分支限定符(branch qualifier),如果没有提供bqual,那么默认值为空字符串’’。

formatID:是一个数字,用于标记gtrid和bqual值的格式,这是一个无符号整数(unsigned integer),也就是说,最小为0。如果没有提供formatID,那么其默认值为1。

特别需要注意的是,xid作为一个事务分支的标识符,理论上只要有分支限定符(bqual)就可以了,为什么要包含全局事务标识符(gtrid)?这主要是为了管理方便,通过包含进xid,我们可以很容易的判断出这个事务分支属于哪一个全局事务。

例如,前面提到 XA RECOVER命令的作用是列出所有处于PREPARE阶段的XA事务,以下是一个案例:

mysql>XA RECOVER;

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

|formatID|gtrid_length|bqual_length|data|

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

|1|6|6|g12345b67890|

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

这里列出的是一个分支事务xid的组成信息,根据前面的介绍,我们可以推断出:

gtrid是data[0]到data[gtrid_length-1]部分的内容,即data[0]到data[6-1=5]部分的内容,结果为g12345;

而bqual是data[gtrid_length]到data[gtrid_length+bqual_length-1]部分的内容,即data[6]到data[6+6-1=11]部分的内容,结果b67890。

因此,根据这个信息,我们就可以判断出这个xid表示的是:全局事务(g12345)中的事务分支(b67890)。

PHP使用XA例子

classconnDb{

privatestatic$host='127.0.0.1:3306';

privatestatic$username='root';

privatestatic$password='root';

privatestatic$dbName='test';

private$conn=null;

publicfunction__construct(){

$this->conn=newMySQLi(self::$host,self::$username,self::$password,self::$dbName);

if(!$this->conn){

die('数据库连接错误:'.$this->conn->connect_error);

}else{

echo'连接成功';

}

$this->conn->query("set names utf-8");

}

publicfunctionexecute_xa($sql){

$this->conn->query($sql);

}

publicfunctionexecute_dml($sql){

$rs=$this->conn->query($sql);

if(!$rs){

$flag=0;

die('数据库操作出错:'.$this->conn->error);

}elseif($this->conn->affected_rows>0){

$flag=1;

}else{

$flag=2;

}

return$flag;

}

publicfunctioncloseConn(){

$this->conn->close();

}

}

testAction();

functiontestAction(){

$XA=uniqid("");

$conn1=newconnDb();

$conn2=newconnDb();

$sql1="update account set money = money - 100 where name = 'czz'";

$sql2="update account set money = money + 100 where name = 'cmq'";

$conn1->execute_xa("XA START '$XA'");

$conn2->execute_xa("XA START '$XA'");

try{

$add_status=$conn1->execute_dml($sql1);

$del_status=$conn1->execute_dml($sql2);

$conn1->execute_xa("XA END '$XA'");

$conn2->execute_xa("XA END '$XA'");

$conn1->execute_xa("XA PREPARE '$XA'");

$conn2->execute_xa("XA PREPARE '$XA'");

if($add_status!=1||$del_status!=1){

thrownewException("操作失败");

}

echo'程序运行成功!';

$conn1->execute_xa("XA COMMIT '$XA'");

$conn2->execute_xa("XA COMMIT '$XA'");

}catch(Exception$ex){

echo'程序运行失败!';

$conn1->execute_xa("XA ROLLBACK '$XA'");

$conn2->execute_xa("XA ROLLBACK '$XA'");

}

}

php mysql xa_分布式事务之——MySQL对XA事务的支持相关推荐

  1. MySQL 5.7 XID乱码情况下XA事务回滚处理方法

    用以下语句输出16进制XID: XA RECOVER CONVERT XID 返回示例: 0xDE1DD62DEA2341C9845B24600B661C1A000000000000000000000 ...

  2. MySQL分布式事务(XA事务)

    MySQL分布式事务(XA事务) 官网:https://dev.mysql.com/doc/refman/5.7/en/xa.html 1.什么是分布式事务 分布式事务就是指事务的参与者.支持事务的服 ...

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

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

  4. 深入解析:MySQL对分布式事务 XA Transactions 的支持

    导读:MySQL对分布式事务(XA Transactions)进行了很好的支持,我们看看它是怎么做的,并实战验证其提供的分布式事务控制语句效果. MySQL从5.0.3开始,InnoDB存储引擎支持X ...

  5. MySQL数据库分布式事务XA实现原理分析

    MySQL XA分为两类,内部XA与外部XA;内部XA用于同一实例下跨多个引擎的事务,由大家熟悉的Binlog作为协调者;外部XA用于跨多MySQL实例的分布式事务,需要应用层介入作为协调者(崩溃时的 ...

  6. mysql事务控制(xa分布式事务)和锁定语句_MySQL的SQL语句 -事务性语句和锁定语句(7)- XA 事务...

    XA 事务 InnoDB 存储引擎支持 XA 事务.MySQL XA 的实现基于 X/Open CAE 文档 Distributed Transaction Processing: The XA Sp ...

  7. jta mysql_springboot + jta + mysql + mongo 分布式(多种数据源)事务

    该文章讲的不是仅mysql的多数据源. 环境: mysql: 5.1.27 mongodb: 4.2.2 springboot: 2.2.2 在前n天遇到一个业务是用到mysql和mongo.都有写操 ...

  8. Mysql的分布式事务原理理解

    本文主要讲解:Mysql的分布式事务原理及中间会遇见的问题 目录 一.事务的特性与类型 二.本地事务 三.并发事务带来的问题 四.事务隔离级别 五.各种类型的锁 六.死锁问题 七.MVCC机制 八.R ...

  9. mysql sql 事务写作_mysql中的事务

    MySQL事务相关 一. 什么是事务 事务(Transaction)是一个逻辑序列,该序列要么执行,要么不执行. 例如:转换业务 A 给 B 转账 1000 元,设计两个操作: A减少1000元 B增 ...

最新文章

  1. Data Mining的十种分析方法
  2. 视觉slam学习--坐标系变换 | 欧式变换+仿射变换+射影变换
  3. Android数据的四种存储方式SharedPreferences、SQLite、Content Provider和File (二) —— SQLite...
  4. Teams App设备的地理位置能力
  5. JDK 1.5新特性
  6. 使用MAT工具分析内存溢出
  7. 从技术到产品,转型的这一年我明白了很多道理
  8. Latex文本文档的排版
  9. atomic_fetch_add
  10. 毕设项目 - 基于SSM的旅游资源网站(含源码+论文)
  11. win10隐藏桌面功能
  12. 手机版服务器最新的,我的世界手机版服务器ip地址大全(持续更新)
  13. [SDOI2015]寻宝游戏
  14. Solidity智能合约案例——投票存在的问题
  15. HTML网页上播放AVI视频代码示例
  16. 金融工程与并行计算:第二章 仿真法在财务工程的使用 Part 2
  17. kubernetes 1.10.3 cAdvisor + Heapster + InfluxDB + Grafana
  18. 《城市大脑系列建设标准规范》立项评审会胜利召开
  19. 打印显示服务器脱机win10,win10网络打印机脱机怎么办?
  20. 软件测试工程师简历项目经验怎么写?--1000套软件测试工程师简历

热门文章

  1. BCH再度领涨,BTC能否及时跟上
  2. #JS:this的指向及函数调用对this的影响
  3. eclipse 全局替换
  4. 程序员请不要问“在吗?”
  5. 在 Google Go Team 工作是一种怎样的体验?
  6. Ubuntu下 安装 window 虚拟机
  7. Android SlideAndDragListView,一个可排序可滑动item的ListView
  8. C#如何把List of Object转换成List of T具体类型
  9. PhoneGap app 性能研究小结(2013网页装在兜里)
  10. 1.1.3 以类为单位的编程思想