mysql xa不保证跨库一致性,仅提供2pc框架;一致性须由应用层或外部事务管理器兜底,否则易致部分提交、悬挂事务及主从错乱;xa start/end/prepare须严格配对,漏xa end将使事务卡在active状态且无法被xa recover发现。

MySQL XA 本身不保证跨库一致性,它只提供两阶段提交(2PC)的协议框架;真正的一致性必须由应用层或外部事务管理器兜底,否则极易出现部分提交、悬挂事务、主从状态错乱等生产事故。
XA START / END / PREPARE 必须严格配对执行
漏掉 XA END 是最常见也最隐蔽的错误:事务会卡在 ACTIVE 状态,既不能 XA PREPARE,也无法被 XA RECOVER 发现,最终耗尽连接池或引发锁等待超时。
-
XA START 'tx1'后必须紧跟着业务 SQL,完成后立刻执行XA END 'tx1';中间不能有异常跳过,也不能依赖连接关闭自动清理 -
XA END之后不能再执行任何 DML,否则报ERROR 1397 (XAE05): XAER_RMFAIL - 建议封装成带 panic 捕获的函数:Go 中用
defer确保XA END执行;Java 中用try-with-resources+XAResource.end()
XA PREPARE 成功 ≠ 事务安全,失败也不等于回滚完成
XA PREPARE 是临界点——成功表示资源已锁定、undo/redo 日志已刷盘,但此时事务仍处于 “prepared” 状态,数据未真正落库;失败则可能因磁盘满、binlog 写入失败、MyISAM 表混用等导致静默丢弃,而 XA RECOVER 查不到记录。
- 崩溃重启后,
XA RECOVER只显示那些成功写入 redo 且被 InnoDB 记录的 prepared 事务 - 若 crash 发生在
prepare之后、commit之前,且 binlog 未刷盘,该事务就“消失”了,只能靠备份恢复 -
XA RECOVER输出的DATA字段是 base64 编码的 XID,需解码确认对应业务单号,避免误XA ROLLBACK已在其他节点提交的事务
MySQL 不是协调者,跨实例 XA 实际是应用层硬编排
MySQL 官方不支持跨实例自动 XA 协调。所谓“多 MySQL 实例 XA”,本质是应用代码分别连不同实例,各自执行 XA START/XA PREPARE,再由自己控制全局提交顺序——这意味着你得手动保证所有 prepare 成功才发 commit,任意一环失败就得全量 rollback,且无法自动重试。
- 上线前必须配置定时任务(如每 5 分钟)执行
XA RECOVER,检查FORMATID和GTRID_LENGTH非零但无后续操作的记录 - MySQL 8.0.29+ 默认启用
binlog_transaction_dependency_tracking = WRITESET,它会重排 XA 分支的 binlog 写入顺序,造成从库上XA COMMIT失败或状态不一致,必须显式设为COMMIT_ORDER - XA 事务必须在同一个 MySQL 连接内完成全部操作,否则
XA RECOVER查不到分支;且不能在存储过程中调用 XA 语句(会报错ERROR 1398 (XAE00): XA statement not allowed inside transaction)
XA 的最大陷阱不在语法,而在它把分布式系统的核心难题——协调者故障恢复、网络分区容忍、参与者状态不一致——全部推给了应用层。一旦没做兜底,prepared 事务就会像幽灵一样卡在 InnoDB 里,既不提交也不释放锁,直到人工介入或服务重启触发隐式 rollback(还未必可靠)。











