现目前处理分布式事务的方案有不少,好比java
而实现了对应的协议的有mysql
对于 XA 协议来讲,它使用的是 2PC 协议的方式,是阻塞式的,而且它还依赖于数据库自身提供的 XA 接口的可靠性,对于大部分商业数据库来讲作的都还蛮不错,在 Mysql 中只有 InnoDB 引擎支持 XA 分布式事务。git
基于 XA 的分布式事务方案更适用于单机应用中跨库事务,它也能够作到远程调用事务支持github
XA 协议由 Tuxedo 首先提出的,并交给X/Open组织,这个组织随即定义了一套分布式事务的标准即 X/Open DTP(X/Open Distributed Transaction Processing Reference Model) 即一些列的接口各个厂商须要遵循这个标准来实现sql
在 DTP 模型中定义了五个组成元素数据库
其中在 DTP 中又定义了如下几个概念编程
DTP 模型主要是经过 2PC 来控制事务管理器和资源管理之间的交互的api
优势:能够作到对业务无侵入,可是对事务管理器和资源管理器要求比较高服务器
缺点:网络
能够看出 2PC 协议存在阻塞低效和数据不一致的问题,因此在大型应用须要较高的吞吐量的应用是不多使用这种方案的
JTA(Java Transaction API)即 Java 事务 API 和 JTS(Java Transaction Service)即 Java 事务服务,他们为 JAVA 平台提供了分布式事务服务,能够把 JTA 理解为是 XA 协议规范的 Java 版本。它也采用的是 DTP 模型
咱们知道 JTA 它只是一个规范,定义了如何去于实现了 XA 协议的资源管理器交互的接口,可是并无对应的实现,官方推荐 Atomikos 来实现 XA 分布式事务,感谢的能够直接取研究 Atomikos 源码。
能够经过对 XA 协议的实际应用来加深咱们的理解,代码以下
public static void test() {
try {
// 开启全局事务
transactionManager.begin();
// 向服务器 A 数据库写入数据
saveDB1();
// 向服务器 B 数据库写入数据
saveDB2();
// 询问 RM 分支事务是否准备就绪
boolean prepareSuccess = transactionManager.prepare();
// 目前没有涉及到远程事务的支持,在本地都是同步的方式调用因此此处没有作作阻塞等待而是返回马上知道是否成功
// 若是涉及到远程事务的支持,那么此处应该就有一个阻塞唤醒机制
if (prepareSuccess) {
// 开始提交分支事务
transactionManager.commit();
} else {
// 回滚
transactionManager.rollback();
}
} catch (Exception e) {
e.printStackTrace();
// 若是出错了就进行回滚各分支事务
try {
transactionManager.rollback();
} catch (Exception e1) {
e1.printStackTrace();
}
} finally {
// 资源回收
GlobalInfo.remove();
}
}
private static void saveDB1() throws XAException, SQLException {
// 由于存在多个数据源,因此须要指定是使用哪个数据源
XAResourceManager xaResourceManager = RMUtil.getResourceManager(dbPool1);
// 分支事务开启
xaResourceManager.begin();
xaResourceManager.execute("insert into test1(name, age) values('pt', 21)");
// 事务执行完毕处于准备阶段等待 TM 下达 commit 指令
xaResourceManager.prepare();
}
private static void saveDB2() throws XAException, SQLException {
XAResourceManager xaResourceManager = RMUtil.getResourceManager(dbPool2);
// 分支事务开启
xaResourceManager.begin();
xaResourceManager.execute("insert into test2(name, age) values('tom', 22)");
// 事务执行完毕处于准备阶段等待 TM 下达 commit 指令
xaResourceManager.prepare();
// 测试回滚
// throw new RuntimeException("xx");
}
复制代码
代码放在了 github 上面感兴趣的能够了解一下
参考: