MySQL数据库分布式事务XA优缺点与改进方案

2024-01-12 12:48

本文主要是介绍MySQL数据库分布式事务XA优缺点与改进方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 MySQL 外部XA分析

1.1 作用分析

  MySQL数据库外部XA可以用在分布式数据库代理层,实现对MySQL数据库的分布式事务支持,例如开源的代理工具:ameoba[4],网易的DDB,淘宝的TDDL,B2B的Cobar等等。

  通过MySQL数据库外部XA,这些工具可以提供跨库的分布式事务。当然,这些工具也就成了外部XA事务的协调者角色。在crash recover时控制悬挂事务是全局commit,或者rollback。

  在crash recover之后,外部应用程序可能会遇到以下几种情况:

  • 情况一:分布式事务对应的MySQL数据库实例,部分完成prepare,部分未完成prepare。此时直接回滚完成prepare的实例即可。n_prepared < Total Nodes (处于prepare状态的节点数量要小于参与分布式事务的所有节点总数)。
  • 情况二:分布式事务对应的MySQL实例,全部完成prepare,未开始进行commit。此时即可提交此事务,也可回滚此事务(根据分布式事务原理,所有节点都完成prepare,应该提交)。n_prepared = Total Nodes。
  • 情况三:分布式事务对应的MySQL实例,全部完成prepare,并且部分节点已经完成commit。此时应该提交该事务处于prepare状态的节点。n_prepared < Total Nodes。对比情况三与情况一,仅仅通过prepare节点的数量无法区分,因此应用程序需要在prepare完成之后记录日志(此时,应用程序起着事务协调者(Transcaction Coordinator)的角色,而根据MariaDB WorkLog#132[5]的说法,TC角色是可以进行”middle engine”优化的,不需要prepare过程,所有MySQL节点xa prepare返回之后,应用程序直接写commit标识即可,然后再对每个MySQL节点进行xa commit操作。),从而用于区分情况一与情况三。
  • 情况四:分布式事务对应的MySQL实例,全部完成commit。此时事务已经提交成功,xid不会出现在执行xa recover的任一个节点。不需要特殊处理。
  • 情况五:未记录任何prepare日志。那么所有的事务,在各个存储引擎的crash recover时,都会被回滚,不需要外部特殊处理。

1.2 MySQL外部XA不足

  通过前面的分析,可知应用程序配合MySQL的XA事务功能,能够较好的支持分布式环境下的事务。但是,这个支持并不完美,根据我的分析,有可能会出现以下几个问题:

  l 问题一:主备数据库的数据不一致。

  MySQL数据库的主备数据库的同步,通过Binlog的复制完成。而Binlog是MySQL数据库内部XA事务的协调者,并且MySQL数据库为binlog做了优化——binlog不写prepare日志,只写commit日志。

  考虑前面提到的情况二,所有的参与节点prepare完成,在进行xa commit前crash。crash recover如果选择commit此事务。由于binlog在prepare阶段未写,因此主库中看来,此分布式事务最终提交了,但是此事务的操作并未写到binlog中,因此也就未能成功复制到备库,从而导致主备库数据不一致的情况出现。

  在MySQL 5.5.16版本中做过测试,这个问题实际存在。crash recover之后,对xa recover返回的事务运行xa commit,对应事务提交,但是操作并未写入binlog,因此无法复制到备库。

  那么是否回滚所有prepare的事务,就可以避免此问题呢?结论是仍旧不行,不仅不能解决问题一,甚至可能引起问题二。

  l 问题二:同一事务,在各参与节点,最终状态不一致(部分提交,部分回滚)。

  若回滚所有prepare状态的分布式事务,会产生问题二。考虑情况三(所有节点完成prepare,部分节点完成commit),该分布式事务对应的节点,部分已经提交,无法回滚,而部分节点回滚。最终导致同一分布式事务,在各参与节点,最终状态不一致。

  l 问题三:源码级别问题。MySQL 5.1.49源码对于外部XA事务处理存在bug,在MySQL 5.5.16版本中,此bug已经被fix。经过验证发现,在我已下载的MySQL 5.1.61与之后的所有版本,此bug均已经被fix。

  在MySQL 5.1.49中,所有xa recover返回的外部xid,都不能被提交。原因如下:

  当运行xa commit ‘xid_name’命令时,MySQL会判断当前xid_name的错误信息,若存在错误信息,那么就在内部将xa commit命令强制转换为xa rollback。xid_name的状态存于xid_cache中,在crash recover阶段,由函数Handler.cc::xarecover_handlerton调用xid_cache_insert(&xid_cache, x)函数完成插入。MySQL 5.1.49在实现xid_cache_insert函数有bug。

  …

  xs->xa_state=xa_state;

  xs->xid.set(xid);

  xs->in_thd=0;

  xs->rm_error=0;

  res=my_hash_insert(&xid_cache, (uchar*)xs);

  …

  MySQL 5.1.49中,缺少了xs->rm_error =0这一行,未初始化rm_error,导致xa commit时判断出错,无法commit。MySQL 5.5.16已经fix此bug,加上了黑色这一行的初始化,应用程序可以xa commit。

1.3 不足的解决方案

  从MySQL数据库外部分布式事务XA不足的分析可以看出,除了实现bug之外,产生其余两个问题的最大原因,还是在于MySQL针对binlog做的 ”middle engine” 优化,binlog的prepare不写日志。在MySQL内部XA事务中,这个优化是可行的,因为Binlog本身的角色就是事务协调者(Transaction Coordinator),事务协调者可以不进行prepare [5]。

  但是对于MySQL外部XA事务,Binlog已经不是事务协调者的角色,其也是一个参与者,或者说是Resource Manager。因此Binlog的prepare日志是不可省略的。

  为了解决MySQL数据库外部XA分布式事务crash recover过程中出现的问题,我觉得只能修改binlog模块。使binlog模块在正常运行过程中也区分内部XA事务与外部XA事务。内部XA事务可以仍旧沿用现在的方案;而外部XA分布式事务,需要增加写prepare日志的功能,已经crash recover时处理prepare日志的功能。

2 参考资料

  [1] Sergei Golubchik. Distributed Transaction Processing with MySQL XA

  [2] http://dev.mysql.com/doc/refman/5.1/en/xa.html

  [3] X/Open. Distributed TP: The XA Specification

  [4] 陈思儒. Amoeba

  [5] MariaDB WorkLog: Transaction coordinator plugin

该文章出自http://jishu.zol.com.cn/4306.html

这篇关于MySQL数据库分布式事务XA优缺点与改进方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/597920

相关文章

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

mysql8.0.43使用InnoDB Cluster配置主从复制

《mysql8.0.43使用InnoDBCluster配置主从复制》本文主要介绍了mysql8.0.43使用InnoDBCluster配置主从复制,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录1、配置Hosts解析(所有服务器都要执行)2、安装mysql shell(所有服务器都要执行)3、

前端缓存策略的自解方案全解析

《前端缓存策略的自解方案全解析》缓存从来都是前端的一个痛点,很多前端搞不清楚缓存到底是何物,:本文主要介绍前端缓存的自解方案,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、为什么“清缓存”成了技术圈的梗二、先给缓存“把个脉”:浏览器到底缓存了谁?三、设计思路:把“发版”做成“自愈”四、代码

解决docker目录内存不足扩容处理方案

《解决docker目录内存不足扩容处理方案》文章介绍了Docker存储目录迁移方法:因系统盘空间不足,需将Docker数据迁移到更大磁盘(如/home/docker),通过修改daemon.json配... 目录1、查看服务器所有磁盘的使用情况2、查看docker镜像和容器存储目录的空间大小3、停止dock

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S

k8s中实现mysql主备过程详解

《k8s中实现mysql主备过程详解》文章讲解了在K8s中使用StatefulSet部署MySQL主备架构,包含NFS安装、storageClass配置、MySQL部署及同步检查步骤,确保主备数据一致... 目录一、k8s中实现mysql主备1.1 环境信息1.2 部署nfs-provisioner1.2.

MySQL中VARCHAR和TEXT的区别小结

《MySQL中VARCHAR和TEXT的区别小结》MySQL中VARCHAR和TEXT用于存储字符串,VARCHAR可变长度存储在行内,适合短文本;TEXT存储在溢出页,适合大文本,下面就来具体的了解... 目录一、VARCHAR 和 TEXT 基本介绍1. VARCHAR2. TEXT二、VARCHAR