翻译官网 13.3.7 部分XA事务部分,有删减。
简单概括:
分布式事务组成
mysql server 作为 RM
客户端作为 TM
分布式事务流程
全局事务的所有分支 (RM) 完成自己的操作
2pc 流程
1 阶段:
所有分支准备就绪,集 RM 将分支操作记录在稳定存储中
2 阶段:
TM 告诉 RM 是提交还是回滚
如果所有分支在准备就绪时都表示可以提交,则通知所有分支提交。
如果任何分支在准备就绪时指示它无法提交,则所有分支都被告知回滚。
优化
在某些情况下,全局事务可能使用单阶段提交 (1PC)。
当事务管理器发现全局事务仅包含一个事务资源(即单个分支)时,可以告知该资源同时准备和提交。
13.3.7 XA Transactions 原文
XA 支持分布式事务,即允许多个单独的事务资源 (RM) 参与全局事务的能力。
全局事务涉及几个本身具有事务性的操作,但是所有操作必须要么作为一个组成功完成,要么全部作为一个组回滚。
从本质上讲,这将 ACID 属性扩展到 “一个级别”,以便可以将多个 ACID 事务作为具有 ACID 属性的全局操作的组成部分一起执行。
(与非分布式事务一样,如果您的应用程序对读取现象敏感,则 SERIALIZABLE 可能是首选。REPEATABLE READ 可能不足以进行分布式事务。)
Applications that use global transactions involve one or more Resource Managers and a Transaction Manager:
使用全局事务的应用程序涉及一个或多个资源管理器(RM)和一个事务管理器 ™:
A Resource Manager (RM) provides access to transactional resources. A database server is one kind of resource manager. It must be possible to either commit or roll back transactions managed by the RM.
资源管理器 (RM) 提供对事务性资源的访问。数据库服务器是一种资源管理器。必须能够提交或回滚 RM 管理的事务。
A Transaction Manager ™ coordinates the transactions that are part of a global transaction. It communicates with the RMs that handle each of these transactions. The individual transactions within a global transaction are “branches” of the global transaction. Global transactions and their branches are identified by a naming scheme described later.
事务管理器 ™ 协调作为全局事务一部分的事务。它与处理每个事务的 RM 通信。全局事务中的各个事务 是全局事务的“分支”。全局事务及其分支,由后面描述的命名方案标识。
The MySQL implementation of XA enables a MySQL server to act as a Resource Manager that handles XA transactions within a global transaction. A client program that connects to the MySQL server acts as the Transaction Manager.
mysql server 作为 RM 角色,用于处理全局事务中的 XA 事务。
连接到 mysql server 的客户端程序,作为 TM 角色。
To carry out a global transaction, it is necessary to know which components are involved, and bring each component to a point when it can be committed or rolled back. Depending on what each component reports about its ability to succeed, they must all commit or roll back as an atomic group. That is, either all components must commit, or all components must roll back. To manage a global transaction, it is necessary to take into account that any component or the connecting network might fail.
要执行全局事务,必须知道涉及哪些组件 (RM),并将每个组件(RM) 带到可以提交或回滚的阶段。
根据每个组件报告其成功能力的情况 (就是每个 RM 报告自己事务能否成功执行),它们都必须作为原子组全部提交或回滚。
也就是说,要么所有组件都必须提交,要么所有组件都必须回滚。
要管理全局事务,必须考虑到任何组件或连接网络都可能发生故障。
The process for executing a global transaction uses two-phase commit (2PC). This takes place after the actions performed by the branches of the global transaction have been executed.
执行全局事务的过程使用两阶段提交 (2PC)。
这是在执行了全局事务的分支所执行的动作之后发生的。
In the first phase, all branches are prepared. That is, they are told by the TM to get ready to commit. Typically, this means each RM that manages a branch records the actions for the branch in stable storage. The branches indicate whether they are able to do this, and these results are used for the second phase.
在第一阶段,所有分支都已准备就绪。也就是说,TM 告诉他们准备提交。
通常,这意味着管理分支的每个 RM 都将分支的操作记录在稳定存储中。
分支指示它们是否能够执行此操作,这些结果用于第二阶段。
In the second phase, the TM tells the RMs whether to commit or roll back. If all branches indicated when they were prepared that they can commit, all branches are told to commit. If any branch indicated when it was prepared that it could not commit, all branches are told to roll back.
在第二阶段,TM 告诉 RM 是提交还是回滚。
如果所有分支在准备就绪时都表示可以提交,则通知所有分支提交。
如果任何分支在准备就绪时指示它无法提交,则所有分支都被告知回滚。
In some cases, a global transaction might use one-phase commit (1PC). For example, when a Transaction Manager finds that a global transaction consists of only one transactional resource (that is, a single branch), that resource can be told to prepare and commit at the same time.
在某些情况下,全局事务可能使用单阶段提交 (1PC)。例如,当事务管理器发现全局事务仅包含一个事务资源(即单个分支)时,可以告知该资源同时准备和提交。
mysql xa 事务语句
xa start xid
xa end xid
xa prepare xid
xa commit xid
xa rollback xid
xa recover xid
返回 mysql 服务器上处于 prepare 状态的所有 xa 事务信息
xid 组成
正常就一个 gtrid,全局唯一
要在 MySQL 中执行 XA 事务,请使用以下语句:
XA {START|BEGIN} xid [JOIN|RESUME]
XA END xid [SUSPEND [FOR MIGRATE]]
XA PREPARE xid
XA COMMIT xid [ONE PHASE]
XA ROLLBACK xid
XA RECOVER [CONVERT XID]
对于 XA START,可以识别 JOIN
和 RESUME
子句,但无效。
对于 XA END,可以识别 SUSPEND [FOR MIGRATE]
子句,但无效。
每个 XA 语句都以 XA
关键字开头,并且大多数都需要 xid
值。
xid
是 XA 事务标识符。它指示该语句适用于哪个事务。
xid
值由 Client 端提供,或由 MySQL 服务器生成。
xid
的值由一到三部分组成:
xid: gtrid [, bqual [, formatID]]
gtrid
是全局事务标识符, bqual
是分支限定符,并且 formatID
是标识 gtrid
和 bqual
值所使用的格式的数字。
如语法所示,bqual
和 formatID
是可选的。
如果未指定,默认 bqual
值为 ''
。如果未指定,则默认值 formatID
为 1.
gtrid
和 bqual
必须是字符串 Literals,每个字符串的长度最多为 64 个字节 (不是字符)。
gtrid
和 bqual
可以通过几种方式指定。您可以使用带引号的字符串 ('ab'
),十六进制字符串(X'6162'
,0x6162
) 或位值(b'nnnn'
)。
formatID
是无符号整数。
gtrid
和 bqual
值由 MySQL 服务器的基础 XA 支持例程以字节为单位进行解释。但是,在解析包含 XA 语句的 SQL 语句时,服务器将使用某些特定的字符集。为了安全起见,将 gtrid
和 bqual
写为十六进制字符串。
xid
值通常由事务管理器生成。一个 TM 生成的值必须不同于其他 TM 生成的值。给定的 TM 必须能够识别 XA RECOVER 语句返回的值列 table 中自己的 xid
值。
XA START xid 使用给定的 xid
值开始 XA 事务。每个 XA 事务必须具有唯一的 xid
值,因此该值当前不能被另一个 XA 事务使用。使用 gtrid
和 bqual
值评估唯一性。必须使用与 XA START 语句中给定的相同值 xid
来指定用于 XA 事务的所有以下 XA 语句。如果使用这些语句中的任何一条,但是指定的 xid
值与某些现有 XA 事务不对应,则将发生错误。
一个或多个 XA 事务可以是同一全局事务的一部分。给定全局事务中的所有 XA 事务必须在 xid
值中使用相同的 gtrid
值。因此, gtrid
值必须是全局唯一的,以使给定 XA 事务属于哪个全局事务没有歧义。 xid
值的 bqual
部分对于全局事务中的每个 XA 事务必须不同。 (bqual
值必须不同,这是当前 MySQL XA 实现的限制. 它不是 XA 规范的一部分.)
XA RECOVER 语句返回 MySQL 服务器上处于 PREPARED
状态的 XA 事务的信息。 (请参阅 第 13.3.7.2 节“ XA 事务状态”。) 无论服务器是由哪个 Client 端启动的,输出都会为服务器上的每个此类 XA 事务包含一行。
XA RECOVER 输出行看起来像这样 (例如 xid
由 'abc'
,'def'
和 7
组成的值):
XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+--------+
| 7 | 3 | 3 | abcdef |
+----------+--------------+--------------+--------+
输出列具有以下含义:
formatID
是 Transaction 的 formatID
部分 xid
gtrid_length
是 xid
的 gtrid
部分的字节长度
bqual_length
是 xid
的 bqual
部分的字节长度
data
是 xid
的 gtrid
和 bqual
部分的串联
XID 值可能包含不可打印的字符。从 MySQL 5.7.5 开始,XA RECOVER 允许使用可选的 CONVERT XID
子句,以便 Client 端可以请求十六进制的 XID 值。
XA 事务通过以下状态进行:
使用 XA START 启动 XA 事务,并将其置于 ACTIVE 状态。
对于 ACTIVE 状态的 XA 事务,发出组成该事务的 SQL 语句(就是执行你要执行的sql),然后发出 XA END 语句。 XA END 将事务置于 IDLE 状态。
对于 IDLE XA 事务,您可以发出 XA PREPARE 语句或 XA COMMIT ... ONE PHASE
语句:
XA PREPARE 将事务置于 PREPARED 状态。此时的 XA RECOVER 语句将在其输出中包含事务的 xid 值,因为 XA RECOVER 列出了处于 PREPARED 状态的所有 XA 事务。
XA COMMIT ... ONE PHASE
准备并提交事务。xid 的值不会被 XA RECOVER 列出,因为事务终止。
对于 PREPARED 状态的 XA 事务,您可以发出 XA COMMIT 语句来提交和终止该事务,或发出 XA ROLLBACK 来回滚并终止该事务。
这是一个简单的 XA 事务,它作为全局事务的一部分在 table 中插入一行:
-- 在mysql上执行
XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)
INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)
XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)
XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)
XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)
在给定的 Client 端连接的上下文中,XA 事务和本地 (非 XA) 事务是互斥的。
例如,如果已发出 XA START 以开始 XA 事务,则在 XA 事务已提交或回滚之前无法启动本地事务。
相反,如果本地事务以 START TRANSACTION 开始,则在提交或回滚该事务之前,不能使用 XA 语句。
如果 XA 事务处于 ACTIVE 状态,则不能发出任何导致隐式提交的语句。
这将违反 XA 协议,因为您无法回滚 XA 事务。
如果您尝试执行这样的语句,则会收到以下错误:(就是说xa start 到 xa end 之间,不能提交事务。需要在prepare阶段及其之后操作)
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed
when global transaction is in the ACTIVE state