XA 事务支持仅限于 InnoDB
存储引擎。
对于 “外部 XA”,MySQL 服务器充当资源管理器,而客户端程序充当事务管理器。对于 “内部 XA”,MySQL 服务器内的存储引擎充当 RM,而服务器本身充当 TM。内部 XA 支持受各个存储引擎功能的限制。内部 XA 是处理涉及多个存储引擎的 XA 事务所必需的。内部 XA 的实现要求存储引擎在表处理程序级别支持两阶段提交,目前只有 InnoDB
支持此功能。
对于 XA START
,JOIN
和 RESUME
子句被识别,但没有效果。
对于 XA END
,SUSPEND [FOR MIGRATE]
子句被识别,但没有效果。
要求 bqual
部分的 xid
值在全局事务中的每个 XA 事务中都不同,这是当前 MySQL XA 实现的限制。它不是 XA 规范的一部分。
XA 事务被写入二进制日志分为两个部分。当发出 XA PREPARE
命令时,事务的第一部分(直到 XA PREPARE
)使用初始 GTID 写入。一个 XA_prepare_log_event
用于在二进制日志中识别此类事务。当发出 XA COMMIT
或 XA ROLLBACK
命令时,事务的第二部分,只包含 XA COMMIT
或 XA ROLLBACK
语句,使用第二个 GTID 写入。请注意,由 XA_prepare_log_event
标识的事务的第一部分并不一定后面紧跟着其 XA COMMIT
或 XA ROLLBACK
,这会导致任何两个 XA 事务的二进制日志交错记录。XA 事务的两个部分甚至可能出现在不同的二进制日志文件中。这意味着处于 PREPARED
状态的 XA 事务现在是持久化的,直到发出显式的 XA COMMIT
或 XA ROLLBACK
语句,确保 XA 事务与复制兼容。
在副本上,XA 事务被准备后立即与复制应用线程分离,并且可以在副本上的任何线程上提交或回滚。这意味着同一个 XA 事务可能在 events_transactions_current
表中以不同的状态出现在不同的线程上。 events_transactions_current
表显示线程上最近监控到的事务事件的当前状态,并且不会在线程处于空闲状态时更新此状态。因此,XA 事务仍可能在原始应用线程中显示为 PREPARED
状态,即使它已被另一个线程处理过。要积极地识别仍然处于 PREPARED
状态且需要恢复的 XA 事务,请使用 XA RECOVER
语句,而不是 Performance Schema 事务表。
使用 XA 事务存在以下限制:
不支持在 XA 事务中使用复制过滤器或二进制日志过滤器。表过滤会导致 XA 事务在副本上为空,而空 XA 事务不受支持。此外,由于副本的连接元数据存储库和应用元数据存储库存储在
InnoDB
表中(默认情况下),数据引擎事务的内部状态会在经过过滤的 XA 事务后发生变化,并可能与复制事务上下文状态不一致。只要 XA 事务受到复制过滤器的影响,无论事务是否因此而为空,都会记录错误
ER_XA_REPLICATION_FILTERS
。如果事务不为空,副本能够继续运行,但您应该采取措施停止在 XA 事务中使用复制过滤器,以避免潜在问题。如果事务为空,副本会停止。在这种情况下,副本可能处于不确定的状态,复制过程的一致性可能会受到损害。特别是,副本副本上的gtid_executed
集可能与源副本上的不一致。要解决此问题,请隔离源并停止所有复制,然后检查整个复制拓扑结构的 GTID 一致性。撤销生成错误消息的 XA 事务,然后重新启动复制。XA 事务被认为对基于语句的复制不安全。如果两个 XA 事务在源上并行提交,并在副本上以相反的顺序准备,则可能会发生无法安全解决的锁定依赖关系,并且复制可能在副本上因死锁而失败。这种情况可能发生在单线程或多线程副本上。当设置
binlog_format=STATEMENT
时,会对 XA 事务内的 DML 语句发出警告。当设置binlog_format=MIXED
或binlog_format=ROW
时,XA 事务内的 DML 语句使用基于行的复制记录,并且潜在问题不存在。您应该注意,当使用相同的事务 XID 依次执行 XA 事务,并在处理
XA COMMIT ... ONE PHASE
期间发生中断时,可能无法再同步二进制日志和存储引擎之间的状态。如果上述一系列事件发生在该事务已在存储引擎中准备完毕之后,而XA COMMIT
语句仍在执行,则可能会发生这种情况。这是一个已知问题。