相关推荐recommended
关于MYSQL的XA事务(分布式事务)的了解以及MySQL5.7.7对XA的优化
作者:mmseoamin日期:2024-04-30

一、关于MySQL XA 事务

    MySQL XA 事务简单说就是基于多数据库的事务,通常用于分布式事务处理当中。比如在分库分表的场景下,当遇到一个用户事务跨了多个分区,需要使用XA事务 来完成整个事务的正确的提交和回滚,即保证全局事务的一致性。

    目前我还没有用过XA事务,我感觉能与XA相关联的可能就是业务与业务间的调用吧,这些工作很多时候都是通过接口来实现两边的数据处理,而接口实现的话需要做到的就是支持数据重入不发生错误,但接口重入肯定没法保证数据一致性,另外也并非每个库都有必要提供接口化服务,这也许就是XA(分布式事务)存在的原因吧。

二、分布式事务的处理规范

    根据 Open Group 关于分布式事务的处理规范,定义了三种组件,如下图:

关于MYSQL的XA事务(分布式事务)的了解以及MySQL5.7.7对XA的优化,第1张

    上图中AP是指应用程序。RM是资源管理器,事务的参与者,通常是数据库,比如MySQL Server。一个分布式事务通常涉及多个资源管理器。TM是事务管理器,创建分布式事务并协调分布式事务中的各个子事务的执行和状态。子事务是指分布式事务中在RM上执行的具体操作。两阶段提交 (Two-Phase Commit, 简称2PC) ,是为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性而设计的一种算法。

三、关于参与者与协调者

    分布式事务通常采用2PC,二阶段提交的算法思路可以概括为: 参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作,这里的参与者可以理解为RM,协调者可以理解为TM。如下图:

关于MYSQL的XA事务(分布式事务)的了解以及MySQL5.7.7对XA的优化,第2张

    在第一阶段,TM会发送 Prepare 到所有参与分布式事务的RM询问是否可以提交操作,参与分布式事务的所有RM接收到请求,实现自身事务提交前的准备工作并返回结果。

    在第二阶段,根据RM返回的结果,如果涉及分布式事务的所有RM都返回可以提交,则TM给RM发送commit的命令,每个RM实现自己的提交,同时释放锁和资源,然后RM反馈提交成功,TM完成整个分布式事务;如果任何一个RM返回不能提交,则涉及分布式事务的所有RM都被告知需要回滚。MySQL XA 也是基于这个规范实现的。

四、MySQL XA与各版本的支持情况

1. MySQL 5.7.7 之前

   MySQL XA 的限制在MySQL 5.7.7 之前,MySQL一直存在一个"bug"。在事务达到PREPARED状态后,客户端断开与MySQL的连接,MySQL 会自动回滚该事务,这个行为不符合分布式事务的规范,MySQL将PREPARED的事务丢失了。之所以MySQL这么实现是因为MySQL 5.7.7 之前PREPARED的事务并不会记录到binlog中。客户端退出后会丢失该信息,如果允许再提交,那么binlog缺少事务信息,会造成主从不一致。

2. MySQL 5.7.7 之后

    在MySQL 5.7.7 之后,MySQL 新增了一个XA_prepare_log_event的事件,会把xa start到xa prepare中间的操作记录到Binlog中。Slave读取Relay log 进行回放,当SQL Thread读取到PREPARED的事务后,在读取xa commit或者xa rollback前,会进行一个类似客户端断开的操作,继续读取后续的事务信息,不会阻塞SQL Thread的执行。从以上的结果看,Oracle在MySQL5.7.7 上确实完美的解决了MySQL XA一直存在的一个"bug"。

    暂时先这么记录着,给自己留个印象,后期有业务需要再细致考虑吧。基本了解是MySQL XA不支持savepoint,之前版本存在出问题很容易导致数据不一致,不合理。而在MySQL 5.7.7版本支持了xa prepare日志从而能保证不会在prepare状态丢失数据。

最后留个版本详细对比的文章地址:https://yq.aliyun.com/articles/213659