简介
RM与TM角色
资源管理器(RM):提供对事务性资源的访问。数据库服务器是一种资源管理器。必须能够提交或回滚由RM管理的事务。XA的MySQL实现使MySQL服务器能够充当资源管理器,在全局事务中处理XA事务。
事务管理器(TM):协调作为全局事务一部分的事务。它与处理每个事务的RMs通信。全局事务中的单个事务是全局事务的“分支”。全局事务及其分支由后面描述的命名方案标识。连接到MySQL服务器的客户机程序充当事务管理器。
two-phase commit(2PC)
1.first phase:在第一阶段,准备好所有分支。也就是说,他们被告知由TM准备提交。通常,这意味着管理分支的每个RM都会在稳定存储中记录分支的操作。分支表示它们是否能够做到这一点,这些结果将用于第二阶段。
2.second phase:TM告诉RMs是提交还是回滚。如果所有分支在准备就绪时都指示它们能够提交,则会通知所有分支提交。如果任何分支在准备时指出它无法提交,那么所有分支都会被告知回滚。
例外
有时候,XA事务(全局事务)可能会使用one-phase commit(1PC)。比如当全局事务管理器发现全局事务只包含一个事务资源的时候,那个资源将被告知同时运行prepare、commit
语法
xid的组成: gtrid [, bqual [, formatID ]] gtrid:全局事务标识符; bqual:分支标识符 formatID:标识gtrid和bqual值使用的格式的数字 如语法所示,bqual和formatID是可选的。如果未给定,则默认bqual值为“”。如果未给定,则默认formatID值为1
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]
注意事项
gtrid和bqual必须是字符串文字,每个文字的长度都不能超过64字节(不是字符)。gtrid和bqual可以用几种方式指定。可以使用带引号的字符串(’ab’)、十六进制字符串(X’6162’,0x6162)或位值(b’nnnn’);formatID是无符号整数;为了安全起见,将gtrid和bqual写为十六进制字符串。
示例
Xid xid1 = new MyXid(100, new byte[] {0x01}, new byte[] {0x02});
Xid xid2 = new MyXid(100, new byte[] {0x11}, new byte[] {0x12});
###展示的data为xid,但显示格式有问题,应为十六进制显示
mysql> XA RECOVER;
+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
| 100 | 1 | 1 | |
+----------+--------------+--------------+------+
1 row in set (0.00 sec)
mysql> XA RECOVER CONVERT XID;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+--------+
| 100 | 1 | 1 | 0x1112 |
+----------+--------------+--------------+--------+
1 row in set (0.00 sec)
###进行回滚
mysql> xa rollback 0x11,0x12,100;
Query OK, 0 rows affected (0.01 sec)
###再次查看
mysql> XA RECOVER CONVERT XID;
Empty set (0.00 sec)
xid值通常由事务管理器生成。一个TM生成的值必须不同于其他TM生成的值。给定的TM必须能够在XA RECOVER语句返回的值列表中识别自己的xid值
一个或多个XA事务可以是同一全局事务的一部分。给定全局事务中的所有XA事务都必须在xid值中使用相同的gtrid值。因此,gtrid值必须是全局唯一的,这样给定的XA事务所属的全局事务就不会有任何歧义。对于全局事务中的每个XA事务,xid值的bqual部分必须不同(要求bqual值不同是当前MySQL XA实现的一个限制。它不是XA规范的一部分。)
官方示例
仅包含RM示例部分
mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+--------+
| 7 | 3 | 3 | abcdef |
+----------+--------------+--------------+--------+
The output columns have the following meanings:
formatID is the formatID part of the transaction xid
gtrid_length is the length in bytes of the gtrid part of the xid
bqual_length is the length in bytes of the bqual part of the xid
data is the concatenation of the gtrid and bqual parts of the xid
XA事务的状态
状态参考https://dev.mysql.com/doc/refman/8.0/en/xa-states.html
如果XA事务处于活动状态,则不能发出任何导致隐式提交的语句(完整隐式提交语句)。这将违反XA契约,因为您无法回滚XA事务
xa与本地事务
在给定客户端连接的上下文中,XA事务和本地(非XA)事务是互斥的。例如,如果发出XA START以开始XA事务,则在提交或回滚XA事务之前,无法启动本地事务。相反,如果使用START transaction启动了本地事务,则在提交或回滚事务之前,不能使用XA语句。
锁超时示例
account表并未建立任何索引。带范围的sql语句会锁住整张表,影响其他会话的执行……与XA和本地事务互斥没有关系。
官方示例
mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)
mysql> update account set money = 1000+10 where name = 'bb';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)
mysql> XA RECOVER;
Empty set (0.00 sec)
mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.01 sec)
mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+--------+
| 1 | 6 | 0 | xatest |
+----------+--------------+--------------+--------+
1 row in set (0.00 sec)
mysql> xa rollback 'xatest';
Query OK, 0 rows affected (0.01 sec)
示例二完整的XID
mysql> XA START 'globalID','bID',100;
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> insert into account select 100,'cc';
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from account;
+-------+------+
| money | name |
+-------+------+
| 1000 | bb |
| 200 | dd |
| 100 | cc |
+-------+------+
3 rows in set (0.00 sec)
mysql> xa end 'globalID','bID',100;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from account;
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state
mysql>
mysql> xa prepare 'globalID','bID',100;
Query OK, 0 rows affected (0.01 sec)
mysql> xa recover;
+----------+--------------+--------------+-------------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+-------------+
| 100 | 8 | 3 | globalIDbID |
+----------+--------------+--------------+-------------+
1 row in set (0.00 sec)
mysql> xa commit 'globalID','bID',100;
Query OK, 0 rows affected (0.01 sec)