会卡住。xa start 后未执行 end 或 commit/rollback 即断连,事务滞留在 xa recover 中呈 prepared 状态,锁不释放、ddl 可能阻塞,且不会自动回滚。

XA START 后没执行 END 就断开,事务会卡住吗
会。MySQL 的 XA 事务在 XA START 后进入 ACTIVE 状态,此时不显式调用 XA END 或直接执行 XA COMMIT/XA ROLLBACK,连接断开后事务不会自动清理,而是滞留在 XA RECOVER 列表里,状态为 PREPARED(部分资源已锁定)。
这种“半悬挂”状态会导致:表级锁或行锁持续占用、后续 DDL 可能被阻塞、INFORMATION_SCHEMA.INNODB_TRX 中看不到它(因为不属于普通事务),但 XA RECOVER 能查到。
- 实操建议:应用层必须保证
XA START→XA END→XA PREPARE→XA COMMIT/ROLLBACK链路完整;网络超时或进程崩溃时,需有兜底机制主动扫描并清理XA RECOVER中的孤儿事务 - 不要依赖连接关闭自动回滚 —— MySQL 不做这事,和普通事务完全不同
-
XA RECOVER返回的data字段是二进制格式,无法直接解读,只能用于后续XA COMMIT ...或XA ROLLBACK ...
XA PREPARE 失败时,为什么有时查不到事务记录
因为 XA PREPARE 是两阶段提交的“第一阶段”,它要求所有参与节点完成本地写入并持久化 undo log,同时将事务状态刷盘标记为 PREPARED。如果在这一步失败(比如磁盘满、binlog 写入失败、InnoDB crash),事务可能只停留在 ACTIVE 状态,甚至根本没注册进 XA 系统。
典型现象:XA RECOVER 查不到记录,但客户端收到 ERROR 1397 (XAE04): XAER_RMFAIL 或 ERROR 1205 (HY000): Deadlock found;这时事务其实已被引擎层自动回滚,无需人工干预。
- 常见误判:看到
XAER_RMFAIL就去查XA RECOVER,结果为空,误以为“丢失了状态”—— 实际是压根没走到 PREPARE 成功那步 -
XA PREPARE成功才意味着真正进入 2PC 流程;失败则退化为单机事务处理逻辑 - 检查
SHOW ENGINE INNODB STATUS的 LATEST DETECTED DEADLOCK 或 LOG SECTION,有时能看到 PREPARE 过程中崩溃的线索
XA COMMIT 执行一半失败(如 coordinator 挂了),从库会不一致吗
不会。MySQL 的 XA 提交强依赖 binlog + InnoDB redo 的一致性,XA COMMIT 是原子操作:只有当 binlog 写入成功且 fsync 完成后,InnoDB 才会清除 prepare 日志并提交。从库靠 relay log 回放 binlog 事件,所以只要主库上 XA COMMIT 成功落盘,从库最终一定同步到相同状态。
但要注意:如果 XA COMMIT 在写 binlog 途中失败(如磁盘 IO hang),整个语句报错,事务仍处于 PREPARED 状态,不会提交也不会丢数据 —— 这正是 XA 的安全边界。
- 真正的风险点在“协调者(应用)发起
XA COMMIT后网络中断,不知道是否成功”:此时必须先查XA RECOVER,再决定是重试 COMMIT 还是执行 ROLLBACK - MySQL 本身不提供“XA 事务状态查询 API”,应用需自己维护 XID 映射关系,或借助外部事务日志表记录每一步动作
- 5.7+ 支持
xa_recover_admin权限控制XA RECOVER输出,生产环境建议限制该权限
MySQL 8.0 的 binlog_transaction_dependency_tracking 对 XA 有影响吗
没有直接影响。该参数控制的是基于 write-set 的并行复制依赖判断逻辑,只作用于普通事务的 binlog event 分组,而 XA 事务的 XA START/XA END/XA PREPARE/XA COMMIT 全部作为独立 event 写入 binlog,且每个 XA 事务天然具备全局唯一 XID,replica 会按 XID 串行回放整个事务链路。
不过间接影响存在:若一个 XA 事务内修改大量数据,开启 WRITESET 可能导致 replica 上该事务被错误地与其他非 XA 事务并行执行,从而破坏跨事务的一致性假设(比如 XA 修改了配置表,后面普通事务读取它)。
- 推荐做法:对涉及 XA 的业务库,设置
binlog_transaction_dependency_tracking=COMMIT_ORDER,避免 write-set 引入不确定性 - XA 事务默认不参与 write-set 计算,但它的 commit event 仍会被当作一个“同步点”,影响后续事务的并行窗口
- 升级到 8.0.30+ 后,
XA RECOVER输出新增formatID和gtrid_length字段,方便与外部 TCC 或 Seata 对齐
XA 的麻烦不在语法多难,而在“事务状态游离于连接之外”——一旦 XID 泄露或上下文丢失,就只能靠人工核对 XA RECOVER 和业务日志来回溯。没人能靠直觉猜出哪个 0x313233... 对应哪笔支付订单。










