mysql xa不能保证跨库强一致性,仅提供2pc框架;真正一致性需应用层或外部事务管理器兜底,否则易致部分提交、悬挂事务及主从错乱。

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已在其他节点提交的事务 - 上线前必须配置定时任务(如每 5 分钟)执行
XA RECOVER,检查FORMATID和GTRID_LENGTH非零但无后续操作的记录
MySQL 不是协调者,跨实例 XA 实际是应用层硬编排
MySQL 官方不支持跨实例自动 XA 协调。所谓“多 MySQL 实例 XA”,本质是应用代码分别连不同实例,各自执行 XA START/XA PREPARE,再由自己控制全局提交顺序——这意味着你得手动保证所有 prepare 成功才发 commit,任意一环失败就得全量 rollback,且无法自动重试。
- MySQL 8.0.29+ 默认启用
binlog_transaction_dependency_tracking = WRITESET,它会重排 XA 分支的 binlog 写入顺序,造成从库上XA COMMIT失败或状态不一致,必须显式设为COMMIT_ORDER - 如果用 ShardingSphere 等中间件,
transactionType=XA要求每个分片库都有undo_log表;缺一个,整个事务 fallback 到本地事务,丢失一致性 - 跨分片的 JOIN 查询天然不一致:A 分片已提交,B 分片还在
prepare,此时读请求可能看到脏数据——只能靠最终一致性 + 版本号/时间戳过滤
最容易被忽略的其实是隔离级别和 binlog 格式:主库用 READ-COMMITTED、从库用 REPEATABLE-READ 会导致主从幻读表现不一致;binlog_format=STATEMENT 在涉及 NOW()、UUID() 等非确定性函数时,从库回放结果与主库不同;GTID 开启后,SET sql_log_bin=0 会破坏 GTID 一致性。











