MySQL中分布式事务2PC的异常恢复

💡 原文中文,约2400字,阅读约需6分钟。
📝

内容提要

分布式事务(XA事务)解决分布式环境中多个数据库或系统事务的复杂性。MySQL中的2PC(两阶段提交)是实现分布式事务的重要机制。使用XA RECOVER命令获取事务ID,然后使用XA COMMIT或XA ROLLBACK命令恢复事务。

🔎

延伸解读

会话中断导致事务卡在准备状态

当应用程序在XA PREPARE和XA COMMIT之间断开会话时,事务会卡在PREPARED状态。此时,MySQL无法自动提交或回滚,事务会一直等待最终裁决。这可能导致行锁或表锁长期占用,引发其他事务超时。通过SHOW ENGINE INNODB STATUS可以看到类似“ACTIVE (PREPARED)”的输出,且TRX_MYSQL_THREAD_ID为0,意味着没有线程可以KILL,重启服务器也无法清除。

使用XA RECOVER获取事务ID

要恢复卡住的事务,首先需要获取事务ID。使用XA RECOVER命令可以列出处于准备状态的事务,但输出不友好。使用XA RECOVER CONVERT XID可以获取十六进制格式的XID。执行该命令需要XA_RECOVER_ADMIN权限,否则会收到错误信息。获取XID后,才能进行后续的提交或回滚操作。

XA COMMIT/ROLLBACK需要拆分XID

XA COMMIT和XA ROLLBACK命令要求XID分为三部分:gtrid、bqual和formatID。gtrid是全局事务标识符,bqual是分支限定符,formatID标识格式。从XA RECOVER的输出中,可以根据gtrid_length和bqual_length列提取gtrid和bqual,formatID则直接获取。然后使用XA COMMIT <gtrid>, <bqual>, <formatID>或XA ROLLBACK <gtrid>, <bqual>, <formatID>来最终解决事务。

❓

Q&A

MySQL中XA事务的典型执行流程包含哪些命令?

XA事务的标准流程包括:XA START <xid>、执行SQL语句、XA END <xid>、XA PREPARE <xid>、XA COMMIT <xid>。其中<xid>是事务协调器生成的唯一事务ID。

为什么MySQL中XA事务会卡在PREPARED状态?

当应用程序在XA PREPARE和XA COMMIT之间断开会话时,事务会卡在准备状态。此时MySQL认为事务仍处于准备状态,等待最终裁决(提交或回滚),但应用程序可能无法访问数据库,导致事务长期滞留。

如何查看MySQL中处于准备状态的XA事务?

可以通过SHOW ENGINE INNODB STATUS命令查看,输出中会显示类似“TRANSACTION 39898344, ACTIVE (PREPARED)”的信息。也可以查询information_schema.innodb_trx表,但注意TRX_MYSQL_THREAD_ID可能为0,表示没有关联的线程。

XA RECOVER命令的作用是什么?需要什么权限?

XA RECOVER命令用于获取处于准备状态的XA事务的XID(事务ID),以便后续提交或回滚。执行该命令需要XA_RECOVER_ADMIN权限,否则会报错。可以使用XA RECOVER CONVERT XID;获得更友好的输出。

XA COMMIT或XA ROLLBACK时如何正确指定XID?

XA COMMIT和XA ROLLBACK需要将XID拆分为三部分:gtrid、bqual和formatID,格式为:XA COMMIT <gtrid>, <bqual>, <formatID>。其中gtrid是XID的前gtrid_length个字节,bqual是接下来的bqual_length个字节,formatID来自formatID列。如果省略bqual,默认值为空字符串;省略formatID,默认值为1。

重启MySQL服务器能清除卡在准备状态的XA事务吗?

不能。重启服务器后,处于准备状态的XA事务仍然存在,等待裁决。必须通过XA COMMIT或XA ROLLBACK命令显式提交或回滚。

🏷️

标签

➡️

继续阅读