Mysql的分布式(XA)真面目
你在学习数据库相关的知识吗?本文《Mysql的分布式(XA)真面目》,主要介绍的内容就涉及到MySQL、Java、数据库,如果你想提升自己的开发能力,就不要错过这篇文章,大家要知道编程理论基础和实战操作都是不可或缺的哦!
一、XA是什么?
XA 协议本就是为一个分布式事务协议,它规定了 XA PREPARE、XA COMMIT、XA ROLLBACK 等命令。XA 协议规定了事务管理器(协调者)和资源管理器(数据节点)如何交互,共同完成分布式 2PC 的过程

XA主要规定了RM与TM之间的交互,下面来看下XA规范中定义的RM 和 TM交互的接口:

xa_start负责开启或者恢复一个事务分支,并且管理XID到调用线程
- xa_end 负责取消当前线程与事务分支的关联
- xa_prepare负责询问RM 是否准备好了提交事务分支
- xa_commit通知RM提交事务分支
- xa_rollback 通知RM回滚事务分支
XA协议是使用了二阶段协议的,其中:
第一阶段TM要求所有的RM准备提交对应的事务分支,询问RM是否有能力保证成功的提交事务分支,RM根据自己的情况,如果判断自己进行的工作可以被提交,那就就对工作内容进行持久化,并给TM回执OK;否者给TM的回执NO。RM在发送了否定答复并回滚了已经的工作后,就可以丢弃这个事务分支信息了。
第二阶段TM根据阶段1各个RM prepare的结果,决定是提交还是回滚事务。如果所有的RM都prepare成功,那么TM通知所有的RM进行提交;如果有RM prepare回执NO的话,则TM通知所有RM回滚自己的事务分支。
也就是TM与RM之间是通过两阶段提交协议进行交互的。
二、MySQL中XA实现
1.内部XA事务
MySQL中只有InnoDB引擎支持XA协议,内部XA事务主要用来协调存储引擎和二进制日志

确认下mysql是否启动了xa功能:

测试手动执行xa事务:

其中首先使用XA START ‘xid' 启动了一个XA事务,并把它置于ACTIVE状态
对于一个ACTIVE状态的 XA事务,我们可以执行构成事务的多条SQL语句,也就是指定分支事务的边界,然后执行一个XA END ‘xid'语句,XA END把事务放入IDLE状态,也就是结束事务边界,在xa start和xa end之间的语句就构成了本分支事务的一个事务范围。当调用xa end 'xid1'后由于结束了事务边界,所以这时候如果在执行sql语句会抛出ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state错误,也就是当分支事务处于IDLE状态时候不允许执行没有包含到分支事务边界里面的其他sql.
对于一个IDLE 状态XA事务,可以执行一个XA PREPARE语句或一个XA COMMIT…ONE PHASE语句,其中XA PREPARE把事务放入PREPARED状态。在此点上的XA RECOVER语句将在其输出中包括事务的xid值,因为XA RECOVER会列出处于PREPARED状态的所有XA事务。XA COMMIT…ONE PHASE用于预备和提交事务,也就是转换为一阶段协议,直接提交事务。
对于一个PREPARED状态的 XA事务,可以执行XA COMMIT 语句来提交或者执行XA ROLLBACK来回滚xa事务。
其中二阶段协议中第一阶段是执行 xa prepare时候,这时候MySQL客户端(TM)向MySQL数据库服务器(RM)发出prepare"准备提交"请求,数据库收到请求后执行数据修改和日志记录等处理,处理完成后只是把事务的状态改成"可以提交",然后把结果返回给事务管理器。
如果第一阶段中数据库都prepare成功,那么mysql客户端(TM)向数据库服务器发出"commit"请求,数据库服务器把事务的"可以提交"状态改为"提交完成"状态,然后返回应答。如果在第一阶段内数据库的操作发生了错误,或者mysql客户端(RM)收不到数据库的回应,则认为事务失败,执行rollback回撤所有数据库的事务。
两阶段提交PC

mysql的两阶段提交原理
(1) perpare阶段 写入redo日志
1、设置undo state=TRX_UNDO_PREPARED;
2、刷事务更新产生的redo日志;
(2) commit阶段 写入binlog日志
1、将事务产生的binlog写入文件,刷入磁盘;
2、设置undo页的状态,置为TRX_UNDO_TO_FREE或TRX_UNDO_TO_PURGE; //标记可以清理回滚段
3、记录事务对应的binlog偏移,写入系统表空间。
两阶段提交是跨系统维持数据逻辑一致性时常用的一个方案。两阶段存在阻塞难题,提出的三阶段提交,在二阶段的基础上增加了一个预提交。
(3)假设法验证为什么分两阶段:
A. 先写 redo log 后写 binlog。假设在 redo log 写完,binlog 还没有写完的时候,MySQL 进程异常重启。由于我们前面说过的,redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 c 的值是 1。
但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。
然后你会发现,如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不同。
B. 先写 binlog 后写 redo log。如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,所以这一行 c 的值是 0。但是 binlog 里面已经记录了“把c 从 0 改成 1”这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 c 的值就是 1,与原库的值不同。
(4)redo和binlog这两种日志有以下三点不同。
1、 redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
2、 redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
3、redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
2.外部XA事务
参与到外部分布式事务中(比如多个数据库实现的分布式事务),目前mysql对外部事务的支持还不够,这里也就不进行太多的描述了。
总结
本篇关于《Mysql的分布式(XA)真面目》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于数据库的相关知识,请关注golang学习网公众号!
GitHub 近期频繁宕机?官方解释:MySQL 负载过重
- 上一篇
- GitHub 近期频繁宕机?官方解释:MySQL 负载过重
- 下一篇
- 详细解读开源 PolarDB 三节点高可用的功能特性和关键技术
-
- 数据库 · MySQL | 3小时前 |
- MySQL 递归 CTE 生成日期序列时为什么列类型会截断
- 104浏览 收藏
-
- 数据库 · MySQL | 7小时前 |
- MySQL 递归 CTE 遍历树数据时怎么防止无限循环
- 142浏览 收藏
-
- 数据库 · MySQL | 10小时前 |
- MySQL invisible index 如何安全观察索引下线影响
- 300浏览 收藏
-
- 数据库 · MySQL | 11小时前 | MySQL · 索引优化 · generated column · mysql 索引 优化器 生成列
- MySQL 生成列索引为什么没有被优化器使用
- 300浏览 收藏
-
- 数据库 · MySQL | 14小时前 |
- MySQL 窗口函数取每组最新记录时如何处理并列时间
- 242浏览 收藏
-
- 数据库 · MySQL | 15小时前 |
- MySQL JSON_VALUE 返回 NULL 时怎么区分缺少路径和空值
- 170浏览 收藏
-
- 数据库 · MySQL | 17小时前 | MySQL · JSON查询 · JSON_TABLE · SQL技巧 · mysql JSON_TABLE FOR ORDINALITY JSON数组序号
- MySQL JSON_TABLE 的 FOR ORDINALITY 怎么保留数组原始序号
- 139浏览 收藏
-
- 数据库 · MySQL | 19小时前 |
- MySQL 复制延迟升高时怎么区分 SQL 线程和 IO 线程
- 304浏览 收藏
-
- 数据库 · MySQL | 21小时前 | MySQL事件 · 事件调度器 · 任务表排查 · mysql 定时任务 CREATE EVENT Event Scheduler INFORMATION_SCHEMA.EVENTS
- MySQL 事件调度器执行了但任务表没有更新怎么排查
- 486浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 52次使用
-
- SuperCLUE
- SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
- 204次使用
-
- C-Eval
- 深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
- 139次使用
-
- AI Prompt Library
- 探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
- 71次使用
-
- Generrated
- Generrated汇集9300+张DALL·E生成图像及对应提示词,支持查看完整图集、对比DALL·E 2与3版本差异,是AI绘图新手学习Prompt设计与获取创作灵感的实用工具。
- 51次使用
-
- MySQL 明明加了索引,为什么查询还是很慢?先查这 6 个点
- 2026-06-27 374浏览
-
- 接口返回的数据和数据库不一致怎么办?按数据生命周期排查
- 2026-06-27 398浏览
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- golang 基于 mysql 简单实现分布式读写锁
- 2023-01-07 384浏览
-
- 详解如何利用GORM实现MySQL事务
- 2023-01-07 184浏览
