13.4.7. XA事务

对于InnoDB存储引擎,可以获得对XA事务的支持。MySQL XA的执行依据X/Open CAE文件Distributed Transaction Processing: The XA Specification。本文件由Open Group出版,可以从http://www.opengroup.org/public/pubs/catalog/c193.htm获取。在I.5节,“对XA事务的限制”对当前XA执行的限制进行了描述。

在客户端方面,没有特殊要求。连接MySQL服务器的XA接口由以XA关键词开头的SQL语句组成。MySQL客户端必须能发送SQL语句,并能理解XA语句接口的语义,但是它们不需要被链接到特定的MySQL客户库上。

当前,在MySQL连接器当中,MySQL连接器/J 5.0.0直接支持XA(也就是,通过一个可以控制XA SQL语句接口的等级接口)。

XA支持分布式的事务,具备能力,让多个独立的事务资源参加全局的事务。事务资源通常是RDBMSs,不过也可以是其它种类的资源。

一个全局事务会涉及到多个行动,这些行动本身是事务性的。不过,所有行动都必须作为一个群组成功完成,或者作为一个群组被回滚。实际上,这会延伸ACID性质,“提高等级”,这样,多个ACID事务就可以一起执行,相当于也拥有ACID性质的全局操作的组件。(但是,对于一个分布式事务,您必须使用SERAILIZABLE隔离等级,以实现ACID性质。对于一个非分布式事务,使用REPEATABLE READ就足够了。但是对于分布式事务,使用REPEATABLE READ是不够的。)

分布式事务的部分示例:

·         应用程序相当于一个把消息传递服务和RDBMS组合在一起的整合工具。应用程序可以确保,所有进行消息发送、回收和处理的事务(同时包含一个事务数据库)均在一个全局事务中发生。您可以把这看作是“事务电子邮件。”

·         应用程序执行的行动会涉及到不同数据库服务器,比如MySQL服务器和Oracle服务器(或多个MySQL服务器)。涉及到多个服务器的行动必须作为一个全局事务的一部分发生,而不是作为针对每个服务器的独立的本地事务发生。

·         银行把帐户信息保存在RDBMS中,并通过自动取款机(ATMs)分发和收取欠款。必须要确保ATM行动被正确地反映到帐户中,但是这不能只由RDBMS单独完成。全局事务管理器会整合ATM和数据库资源,以确保财务事务的整体一致性。

使用全局事务的应用程序涉及一个或多个资源管理器和一个事务管理器:

·         资源管理器(RM)用于提供通向事务资源的途径。数据库服务器是一种资源管理器。该管理器必须可以提交或 回滚由RM管理的事务。

·         事务管理器(TM)用于协调作为一个全局事务一部分的事务。TM与管理每个事务的RMs进行通讯。一个全局事务中各个单个事务均是全局事务的“分支”。全局事务和各分支通过一种命名方法进行标识。这种命名方法在后面进行讲述。

MySQL执行XA MySQL时,MySQL服务器相当于一个用于管理全局事务中的XA事务的资源管理器。与MySQL服务器连接的客户端相当于事务管理器。

要执行一个全局事务,必须知道涉及到了哪些组件,并且把每个组件引到一点,在此时,组件可以被提交或回滚时。根据每个组件报告的有关组件效能的内容,这些组件必须作为一个原子性群组全部提交或 回滚。即,要么所有的组件必须提交,要么所有的组件必须回滚。要管理一个全局事务,必须要考虑任何组件或连接网络可能会故障。

用于执行全局事务的过程使用两阶段提交(2PC),发生时间在由全局事务的分支进行的行动已经被执行之后。

1.    在第一阶段,所有的分支被预备好。即,它们被TM告知要准备提交。通常,这意味着用于管理分支的每个RM会记录对于被稳定保存的分支的行动。分支指示是否它们可以这么做。这些结果被用于第二阶段。

2.    在第二阶段,TM告知RMs是否要提交或 回滚。如果在预备分支时,所有的分支指示它们将能够提交,则所有的分支被告知要提交。如果在预备时,有任何分支指示它将不能提交,则所有分支被告知 回滚。

在有些情况下,一个全局事务可能会使用一阶段提交(1PC)。例如,当一个事务管理器发现,一个全局事务只由一个事务资源组成(即,单一分支),则该资源可以被告知同时进行预备和提交。

13.4.7.1. XA事务SQL语法

要在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

对于XA STARTJOINRESUME子句不被支持。

对于XA ENDSUSPEND [FOR MIGRATE]子句不被支持。

每个XA语句以XA关键词为开头,多数语句要求一个xid值。 xid是一个XA事务标识符。它指示该语句适用于哪个事务。xid值由客户端提供,或由MySQL服务器生成。xid值包含一到三个部分:

xid: gtrid [, bqual [, formatID ]]

gtrid是一个全局事务标识符,bqual是一个分支限定符,formatID是一个数字,用于标识由gtridbqual值使用的格式。根据语法的表示,bqualformatID是自选的。如果没有给定,默认的bqual值是''。如果没有给定,默认的fromatID值是1

gtridbqual必须为字符串文字,每个的长度最多为64字节(不是字符)。gtridbqual可以用多种方法指定。您可以使用带引号的字符串('ab'),十六进制字符串(0x6162, X'ab'),或位值(b'nnnn')

formatID是一个无符号的整数。

通过MySQL服务器的带下划线的XA支持子程序,gtridbqual值被理解为以字节为单位。但是,在包含XA语句的SQL语句正在被分析的同时,服务器会去操作一些特定的字符集。为了安全,把gtridbqual作为十六进制字符串写入。

通常,xid值由事务管理器生成。由一个TM生成的值必须与由其它TMs生成的值不同。一个给定的TM必须能识别自己的xid值。这些值位于由XA RECOVER语句返回的值清单中。

XA START xid用于启动一个带给定xid值的XA事务。每个XA事务必须有一个唯一的xid值,因此该值当前不能被其它的XA事务使用。使用gtridbqual值评估唯一性。所有下列的用于XA事务的XA语句必须使用与XA START语句中给定的相同的xid值进行指定。如果您使用这些语句,但是指定的xid值与部分原有的XA事务不对应的话,会发生错误。

一项或多项XA事务可以是同一个全局事务的一部分。在一个给定的全局事务中的所有XA事务必须在xid值中使用同样的gtrid值。出于这个原因,gtrid值必须为全局唯一的,这样,有关一个给定的XA事务是哪个全局事务的一部分的问题就不会含糊不清。对于一个全局事务中的每个XA事务,xid值中的bqual部分必须不一样。(bqual值应不一样,这个要求是当前执行MySQL XA的一个限制条件。这不是XA规约的一部分。)

对于在MySQL服务器上的处于PREPARED状态的XA事务,XA RECOVER语句会返回信息。(见13.4.7.2节,“XA事务状态”.。)输出包括一个行,该行用于服务器上的每个这类XA事务,不论是哪个客户端启动了它。

XA RECOVER输出行看上去像这样(例如,xid值包括'abc', 'def'7等部分):

mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data   |
+----------+--------------+--------------+--------+
|        7 |            3 |            3 | abcdef |
+----------+--------------+--------------+--------+

输出列有以下意义:

·         formatID是事务xidformatID部分

·         gtrid_lengthxidgtrid部分的长度,以字节为单位

·         bqual_lengthxidbqual部分的长度,以字节为单位

·         dataxidgtrid部分和bqual部分的串联

13.4.7.2. XA事务状态

XA事务在以下状态下进展:

1.    使用XA START来启动一个XA事务,并把它放入ACTIVE状态。

2.    对于一个ACTIVE XA事务,发布构成事务的SQL语句,然后发布一个XA END语句。XA END把事务放入IDLE状态。

3.    对于一个IDLE XA事务,您可以发布一个XA PREPARE语句或一个XA COMMITONE PHASE语句:

·         XA PREPARE把事务放入PREPARED状态。在此点上的XA RECOVER语句将在其输出中包括事务的xid值,因为XA RECOVER会列出处于PREPARED状态的所有XA事务。

·         XA COMMITONE PHASE用于预备和提交事务。xid值将不会被XA RECOVER列出,因为事务终止。

4.    对于一个PREPARED XA事务,您可以发布一个XA COMMIT语句来提交和终止事务,或者发布XA ROLLBACK来回滚并终止事务。

下面是一个简单的XA事务,该事务把一行作为一个全局事务的一部分插入一个表中。

mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)
 
mysql> INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)
 
mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)
 
mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)
 
mysql> XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)

根据一个给定的客户端连接的语境,XA事务和本地(非XA)事务互相排斥。举例说明,如果已经发布了XA START来开始一项XA事务,则本地事务不会被启动,直到XA事务已经被提交或被 回滚为止。相反的,如果已经使用START TRANSACTION启动一个本地事务,则XA语句不能被使用,直到该事务被提交或被 回滚为止。

关注编程学问公众号