一文搞懂MySQL XA如何实现分布式事务
导读
目录
- 前言
- XA 协议
- 如何通过MySQL XA实现分布式事务
前言
MySQL支持单机事务的良好表现毋庸置疑,那么在分布式系统中,涉及多个节点,MySQL又是如何实现分布式事务的呢?比如开发一个业务系统,它接受外部的请求,然后访问多个内部其它系统才能执行该请求。执行时我们需要同时更新多个数据库的值(D1,D2,D3)。由于系统必须处于一个一致性,也就是这三个数据库的值要么同时更新成功,要么全部不更新。不然会造成子系统有些指令成功了,有些指令尚未执行。导致对结果理解混乱。
那么,MySQL如何实现多个MySQL数据库更新的一致性呢?那就是MySQL XA。MySQL正是靠支持XA规范的二阶段提交协议,才实现了多个数据库的操作。
XA 协议
提到XA规范就得来聊一下DTP模型(Distributed Transaction Processing)。XA规范就是约定DTP模型中的两个模块事务管理器和资源管理器的通讯方式。DTP其实就是分布式事务处理
各个模块的作用如下:
- AP(Application Program):应用程序,定义事务边界(定义事务开始和结束)并访问事务边界内的资源。
- RM(Resource Manger)资源管理器: 管理共享资源并提供外部访问接口。供外部程序来访问数据库等共享资源。此外,RM还具有事务的回滚能力。
- TM(Transaction Manager)事务管理器:TM是分布式事务的协调者,TM与每个RM进行通信,负责管理全局事务,分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚、失败恢复等。
刚开始看可能觉得不好理解,总结起来该架构就是应用程序访问及使用资环管理器提供的共享资源,通过事务管理器提供的事务接口(TX interface)定义事务操作。事务管理器和资源管理会基于XA规范执行二阶段提交协议。
XA规范流程如下图所示
- 应用程序AP向事务管理器TM发起事务请求
- TM调用xa_open()建立同资源管理器的会话
- TM调用xa_start()标记一个事务分支的开头
- AP访问资源管理器RM并定义操作,比如插入记录操作
- TM调用xa_end()标记事务分支的结束
- TM调用xa_prepare()通知RM做好事务分支的提交准备工作。其实就是二阶段提交的提交请求阶段。
- TM调用xa_commit()通知RM提交事务分支,也就是二阶段提交的提交执行阶段。
- TM调用xa_close管理与RM的会话。
- 这些接口一定要按顺序执行,比如xa_start接口一定要在xa_end之前。此外,这里千万要注意的是事务管理器只是标记事务分支并不执行事务,事务操作最终是由应用程序通知资源管理器完成的。另外,我们来总结下XA的接口
- xa_start:负责开启或者恢复一个事务分支,并且管理XID到调用线程
- xa_end:负责取消当前线程与事务分支的关系
- xa_prepare:负责询问RM 是否准备好了提交事务分支 xa_commit:通知RM提交事务分支
- xa_rollback:通知RM回滚事务分支
如何通过MySQL XA实现分布式事务
Mysql中存在两种XA事务,一种是内部XA事务主要用来协调存储引擎和二进制日志,一种是外部事务可以参与到外部分布式事务中(比如多个数据库实现的分布式事务),这里我们主要讨论外部事务。
注:MySQL中只有当隔离级别设置为Serializable的时候才能使用分布式事务。
MySQL的XA语法如下
XA {START|BEGIN} xid [JOIN|RESUME] XA PREPARE xid XA END xid XA COMMIT xid[ONE PHASE] XA ROLLBACK xid XA RECOVER[CONVERT XID ]
其中xid作为事务ID,唯一表示一个事务分支,每个事务分支都有一个id。
首先要确认是否开启了XA 功能
设置隔离级别为serializable
执行结果
首先调用“XA START ‘xid' ”命令把XA事务置于ACTIVATE状态,接着执行构成事务的多条SQL语句(比如 update
t1 set c1 = ‘a' where id=1),也就是指定事务的边界。然后调用“XA END ‘xid' ”把事务放入IDLE状态,也就是结束事务边界。
接着,对于一个处于IDLE状态的XA事务,可以执行“XA PREPARE”命令或一个“XA COMMIT…ONE PHASE”命令,XA
PREPARE来执行二阶段提交协议的提交请求阶段。执行“XA RECOVER”命令会列出处于PREPARED状态的所有XA事务。XA
COMMIT…ONE PHASE用于预备和提交事务,也就是转换为一阶段协议,直接提交事务。
最后,调用“XA COMMIT”来提交事务(或者“XA ROLLBACK”回滚事务)。这样就实现了全局事务的一致性了。
通过上面的流程可以看到,在MySQL数据库分布式事务中,MySQL的角色其实是XA事务过程中的RM,TM是连接MySQL服务器的客户端。在分布式事务中一般会涉及到至少两个RM,所以我们说的MySQL支持XA协议是说mysql作为RM来说的,也就是说MySQL实现了XA协议中RM应该具有的功能。