分布式事务(三)mysql对XA协议的支持
系列目录
引子
从Mysql5开始,innoDB引擎支持XA协议的分布式事务。DTP模型中,一个TM(事务管理器管理)管理多个RM(资源管理器),每个RM维护自己的事务分支。在看源码之前我们看一下底层DB mysql对XA事务的支持。
1. XA语法
官网:13.3.8.1 XA Transaction SQL Syntax
1 XA {START|BEGIN} xid [JOIN|RESUME] 开启XA事务,使用begin才能使用join/resume,start不支持
2
3 XA END xid [SUSPEND [FOR MIGRATE]] 不支持SUSPEND [FOR MIGRATE]
4
5 XA PREPARE xid 二阶段提交的准备阶段
6
7 XA COMMIT xid [ONE PHASE] 二阶段提交的提交阶段,ONE PHASE代表一阶段提交,如果只有一个rm参与者,那么二阶段提交优化为一阶段提交
8
9 XA ROLLBACK xid 回滚
10
11 XA RECOVER [CONVERT XID] 列出所有处于prepared状态的事务
上面的语法中都有xid官方解释如下:
xid: gtrid [, bqual [, formatID ]]
其中,
gtrid:全局事务ID,不得超过64,建议使用十六进制数。
bqual:分支限定符(branch qualifier),如果没有提供bqual,那么默认值为空字符串'',长度不超过64,建议使用十六进制数。
formatID:是一个无符号整数,用于标记gtrid和bqual值的格式,默认为1,长度不超过64.
对应java接口:
1 public interface Xid {
2 int MAXGTRIDSIZE = 64;
3 int MAXBQUALSIZE = 64;
4
5 int getFormatId();
6
7 byte[] getGlobalTransactionId();
8
9 byte[] getBranchQualifier();
10 }
2. XA状态
官网:13.3.8.2 XA Transaction States
XA事务的状态,按照如下步骤进行展开
1. 使用XA START来启动一个XA事务,并把它置于ACTIVE状态。
2. 对于一个ACTIVE状态的 XA事务,我们可以执行构成事务的SQL语句,然后发布一个XA END语句。XA END使事务进入IDLE状态。
3. 对于一个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列出,因为事务终止。
4. 对于一个PREPARED状态的 XA事务,执行XA COMMIT语句来提交和终止事务,或者执行XA ROLLBACK来回滚并终止事务。
注意:
同一个客户端数据库连接,XA事务和非XA事务(即本地事务)是互斥的。例如,已经执行了”XA START”命令来开启一个XA事务,则本地事务不会被启动,直到XA事务已经被提交或被 回滚为止。相反的,如果已经使用START TRANSACTION启动一个本地事务,则XA语句不能被使用,直到该事务被提交或被 回滚为止。
3. 测试
package study.xa; import com.mysql.jdbc.jdbc2.optional.MysqlXAConnection;
import com.mysql.jdbc.jdbc2.optional.MysqlXid; import javax.sql.XAConnection;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException; /***
* @Description mysql分布式事务XAConnection模拟
* @author denny
* @date 2019/4/3 上午9:15
*/
public class MysqlXaConnectionTest { public static void main(String[] args) throws SQLException {
//true表示打印XA语句,,用于调试
boolean logXaCommands = true;
// 获得资源管理器操作接口实例 RM1
Connection conn1 = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "12345");
XAConnection xaConn1 = new MysqlXAConnection((com.mysql.jdbc.Connection)conn1, logXaCommands);
XAResource rm1 = xaConn1.getXAResource(); // 获得资源管理器操作接口实例 RM2
Connection conn2 = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2", "root", "12345");
XAConnection xaConn2 = new MysqlXAConnection((com.mysql.jdbc.Connection)conn2, logXaCommands);
XAResource rm2 = xaConn2.getXAResource();
// AP请求TM执行一个分布式事务,TM生成全局事务id
byte[] gtrid = "g12345".getBytes();
int formatId = 1;
try {
// ==============分别执行RM1和RM2上的事务分支====================
// TM生成rm1上的事务分支id
byte[] bqual1 = "b00001".getBytes();
Xid xid1 = new MysqlXid(gtrid, bqual1, formatId);
// 执行rm1上的事务分支 One of TMNOFLAGS, TMJOIN, or TMRESUME.
rm1.start(xid1, XAResource.TMNOFLAGS);
// 业务1:插入user表
PreparedStatement ps1 = conn1.prepareStatement("INSERT into user VALUES ('99', 'user99')");
ps1.execute();
rm1.end(xid1, XAResource.TMSUCCESS); // TM生成rm2上的事务分支id
byte[] bqual2 = "b00002".getBytes();
Xid xid2 = new MysqlXid(gtrid, bqual2, formatId);
// 执行rm2上的事务分支
rm2.start(xid2, XAResource.TMNOFLAGS);
// 业务2:插入user_msg表
PreparedStatement ps2 = conn2.prepareStatement("INSERT into user_msg VALUES ('88', '99', 'user99的备注')");
ps2.execute();
rm2.end(xid2, XAResource.TMSUCCESS); // ===================两阶段提交================================
// phase1:询问所有的RM 准备提交事务分支
int rm1Prepare = rm1.prepare(xid1);
int rm2Prepare = rm2.prepare(xid2);
// phase2:提交所有事务分支
boolean onePhase = false;
//TM判断有2个事务分支,所以不能优化为一阶段提交
if (rm1Prepare == XAResource.XA_OK
&& rm2Prepare == XAResource.XA_OK
) {
//所有事务分支都prepare成功,提交所有事务分支
rm1.commit(xid1, onePhase);
rm2.commit(xid2, onePhase);
} else {
//如果有事务分支没有成功,则回滚
rm1.rollback(xid1);
rm1.rollback(xid2);
}
} catch (XAException e) {
// 如果出现异常,也要进行回滚
e.printStackTrace();
}
}
}
打印日志:
Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA START 0x673132333435,0x623030303031,0x1
Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA END 0x673132333435,0x623030303031,0x1
Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA START 0x673132333435,0x623030303032,0x1
Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA END 0x673132333435,0x623030303032,0x1
Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA PREPARE 0x673132333435,0x623030303031,0x1
Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA PREPARE 0x673132333435,0x623030303032,0x1
Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA COMMIT 0x673132333435,0x623030303031,0x1
Tue Jun 04 17:08:18 CST 2019 DEBUG: Executing XA statement: XA COMMIT 0x673132333435,0x623030303032,0x1
=====参考======
http://www.tianshouzhi.com/api/tutorials/distributed_transaction/384
分布式事务(三)mysql对XA协议的支持的更多相关文章
- [转帖]分布式事务之解决方案(XA和2PC)
分布式事务之解决方案(XA和2PC) https://zhuanlan.zhihu.com/p/93459200 3. 分布式事务解决方案之2PC(两阶段提交) 针对不同的分布式场景业界常见的解决方案 ...
- 【转帖】分布式事务之解决方案(XA和2PC)
分布式事务之解决方案(XA和2PC) https://zhuanlan.zhihu.com/p/93459200 博彦信息技术有限公司 java工程师 3. 分布式事务解决方案之2PC(两阶段提交 ...
- 分布式事务之解决方案(XA和2PC)
3. 分布式事务解决方案之2PC(两阶段提交) 针对不同的分布式场景业界常见的解决方案有2PC.TCC.可靠消息最终一致性.最大努力通知这几种. 3.1. 什么是2PC 2PC即两阶段提交协议,是将整 ...
- 分布式事务(二)Java事务API(JTA)规范
一.引子 既然出现了分布式场景(DTP模型), 大java也及时制定出一套规范来给各大应用服务器.数据库/mq等厂商使用,以方便管理互通--->JTA闪亮登场.JTA(Java Transact ...
- 了解一下Mysql分布式事务及优缺点、使用案例(php+mysql)
在开发中,为了降低单点压力,通常会根据业务情况进行分表分库,将表分布在不同的库中(库可能分布在不同的机器上),但是一个业务场景可能会同时处理两个表的操作.在这种场景下,事务的提交会变得相对复杂,因为多 ...
- 分布式事务、XA、两阶段提交、一阶段提交
本文原文连接:http://blog.csdn.net/bluishglc/article/details/7612811 ,转载请注明出处! 1.XA XA是由X/Open组织提出的分布式事务的规范 ...
- JTA 使用 MySQL 分布式事务
假定在MySQL实例1上有表 create table person( id int, name ) ) MySQL实例2上也有一张同样的表,现在从实例1中的 person 表中删除一条数据,并把这条 ...
- XA事务与MySQL
XA事务就是两阶段提交的一种实现方式 XA规范主要定义了事务管理器TM,和资源管理器RM之间的接口 根据2PC的规范,将一次事务分割成两个阶段 1. prepare阶段 TM向所有RM发送prepar ...
- Spring Cloud Alibaba | 微服务分布式事务之Seata
Spring Cloud Alibaba | 微服务分布式事务之Seata 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud:Green ...
随机推荐
- AndroidSweetSheet:ViewPager的实现(2)
AndroidSweetSheet:ViewPager的实现(2) 附录文章9说明了AndroidSweetSheet典型的列表样式实现,本文写一个例子,说明AndroidSweetSheet以 ...
- caca需要用到x11作为图形输出
编译错误:no output drivers were selected!. yum -y install xcb-proto yum -y install libxcb-devel.x86_64 l ...
- TestNG 练习
java文件 package selniumhomework; import org.testng.annotations.Test; public class Test1 { @Test(group ...
- 面向对象:元类、异常处理(try...except...)
元类: python中一切皆对象,意味着: 1. 都可以被引用,如 x = obj 2. 都可以被当做函数的参数传入 3. 都可以被当做函数的返回值 4. 都可以当做容器类的元素(列表.字典.元祖.集 ...
- codevs1128 导弹拦截
题目描述 Description 经过11 年的韬光养晦,某国研发出了一种新的导弹拦截系统,凡是与它的距离不超过其工作半径的导弹都能够被它成功拦截.当工作半径为0 时,则能够拦截与它位置恰好相同的导弹 ...
- baidu 和 es 使用
http://www.cnblogs.com/kangoroo/p/8047586.html
- [bzoj3160]万径人踪灭_FFT_Manacher
万径人踪灭 bzoj-3160 题目大意:给定一个ab串.求所有的子序列满足:位置和字符都关于某条对称轴对称而且不连续. 注释:$1\le n\le 10^5$. 想法: 看了大爷的题解,OrzOrz ...
- js的声明与引入
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Mybatis教程(一)
1 Mybatis教程(一) 学习过的持久层框架:DBUtils , Hibernate Mybatis就是类似于hibernate的orm持久层框架. 为什么学Mybatis? 目前最主流 ...
- 【SQL Server 学习系列】-- 随机生成日期时间的SQL脚本
DECLARE @dt1 DATETIME,@dt2 DATETIME,@a BIGINT,@b BIGINT SET @dt1='2010-01-01'--开始日期 SET @dt2='2010-0 ...