系列目录

分布式事务(一)原理概览

分布式事务(二)JTA规范

分布式事务(三)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协议的支持的更多相关文章

  1. [转帖]分布式事务之解决方案(XA和2PC)

    分布式事务之解决方案(XA和2PC) https://zhuanlan.zhihu.com/p/93459200 3. 分布式事务解决方案之2PC(两阶段提交) 针对不同的分布式场景业界常见的解决方案 ...

  2. 【转帖】分布式事务之解决方案(XA和2PC)

    分布式事务之解决方案(XA和2PC) https://zhuanlan.zhihu.com/p/93459200 ​ 博彦信息技术有限公司 java工程师 3. 分布式事务解决方案之2PC(两阶段提交 ...

  3. 分布式事务之解决方案(XA和2PC)

    3. 分布式事务解决方案之2PC(两阶段提交) 针对不同的分布式场景业界常见的解决方案有2PC.TCC.可靠消息最终一致性.最大努力通知这几种. 3.1. 什么是2PC 2PC即两阶段提交协议,是将整 ...

  4. 分布式事务(二)Java事务API(JTA)规范

    一.引子 既然出现了分布式场景(DTP模型), 大java也及时制定出一套规范来给各大应用服务器.数据库/mq等厂商使用,以方便管理互通--->JTA闪亮登场.JTA(Java Transact ...

  5. 了解一下Mysql分布式事务及优缺点、使用案例(php+mysql)

    在开发中,为了降低单点压力,通常会根据业务情况进行分表分库,将表分布在不同的库中(库可能分布在不同的机器上),但是一个业务场景可能会同时处理两个表的操作.在这种场景下,事务的提交会变得相对复杂,因为多 ...

  6. 分布式事务、XA、两阶段提交、一阶段提交

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

  7. JTA 使用 MySQL 分布式事务

    假定在MySQL实例1上有表 create table person( id int, name ) ) MySQL实例2上也有一张同样的表,现在从实例1中的 person 表中删除一条数据,并把这条 ...

  8. XA事务与MySQL

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

  9. Spring Cloud Alibaba | 微服务分布式事务之Seata

    Spring Cloud Alibaba | 微服务分布式事务之Seata 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud:Green ...

随机推荐

  1. 乱记结论之OI常用四大数列

    一.斐波那契数列 $f(0)=1,f(1)=1,f(i)=f(i-1)+f(i-2) \ \ \ \ (i>=2)$ 经典的解释是兔子生小孩,第0年一对兔子,一对兔子需要一年长大,后面每年都生小 ...

  2. Avito Code Challenge 2018 C

    C. Useful Decomposition time limit per test 1 second memory limit per test 256 megabytes input stand ...

  3. [bzoj2194]快速傅立叶之二_FFT

    快速傅立叶之二 bzoj-2194 题目大意:给定两个长度为$n$的序列$a$和$b$.求$c$序列,其中:$c_i=\sum\limits_{j=i}^{n-1} a_j\times b_{j-i} ...

  4. Java 代理模式和装饰者模式的区别

    装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案:代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用: 装饰模式应该为所装饰的对象增强功能:代理模式对代理的 ...

  5. 【Nginx】负载均衡-加权轮询策略剖析

    转自:江南烟雨 本文介绍的是客户端请求在多个后端服务器之间的均衡,注意与客户端请求在多个nginx进程之间的均衡相区别. 如果Nginx是以反向代理的形式配置运行,那么对请求的实际处理需要转发到后端服 ...

  6. Django打造大型企业官网(三)

    四.前端首页 4.1.导航条实现 (1)templates/new/index.html <!DOCTYPE html> <html lang="en"> ...

  7. nginx进程和实时控制

    原文地址:http://nginx.com/resources/admin-guide/processes-and-runtime-control/ Processes and Runtime Con ...

  8. Mac下intellij idea环境的项目的新建、配色、快捷键的配置

    注:本文所使用的intellij idea是14.1.2的版本号. 一.项目的新建(以新建Java项目为例) 选中当中的"create new project". 接下来你会看到下 ...

  9. Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序

    Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序 C#原本是用来编写Windows以及Windows Phone的应用程序.自从Xamarin问世后.C#的作用就发生了非常大的变化 ...

  10. Noip模拟 Day6.12

    第一题:贪吃蛇(snake) 本题其实就是判断一个有向图中有没有环,做一次拓扑排序就可以了,如果所有点都入队了,就表示没有环,否则就有环.或者就是dfs一次,每个点只需要被访问一次,这样也是O(n)的 ...