Improvements to XA support in MySQL 5.7

Keywords: MySQL Database Session

introduce

XA, which means "eXtended Architecture", is the standard created by The Open Group for distributed transaction processing. Although MySQL 5.0 is the first version to support XA, MySQL 5.7 improves the reliability of XA support, fixes many errors, and increases overall test case coverage.

background

XA solves the problem of retaining ACID attributes in a single transaction in a distributed resource set. Resources themselves can be other MySQL servers, or even different database technologies. The XA standard describes the interaction between the global transaction manager and the local resource manager.

As mentioned above, MySQL 5.0 introduces XA support, which increases the ability to participate in global transactions. XA needs a resource manager, which provides access to transaction resources, and a transaction manager to coordinate transactions in global transactions. The XA implementation of MySQL enables MySQL servers to act as resource managers, while clients connected to MySQL servers perform transaction managers.

XA uses a two-stage submission protocol, in which the first stage is to submit the request and then the actual submission. Once the branches of the global transaction are executed, the two-phase commit protocol starts:

  1. In the first phase, the transaction manager publishes the ready submission message to all branches involved in the global transaction. Before the resource manager confirms that it is ready for submission, it logs the results of the operation to perform the actual submission in the second phase.
  2. In the second stage, the transaction manager notifies all relevant branches if they receive a positive response. However, if any branch replies in a failed manner, all branches are notified to roll back.

The transaction manager interacts with multiple resource managers to handle each transaction/branch in a global transaction. The diagram depicts XA transactions involving a resource manager. The statement of an XA transaction begins with the XA keyword, the operation to be performed, and the unique identifier. In the following example, the string'xatest'represents the global transaction identifier. In addition to global transaction identifiers, you can specify branch identifiers and format IDs for XA transactions. Branch identifiers are used to identify local transactions, and format IDs specify the formats used by the first two components.

  • XA START / BEGIN starts a transaction and defines its global transaction identifier.
  • XA END specifies the end of an active transaction.
  • XA PREPARE prepares transactions for submission.
  • XA COMMIT [ONE PHASE] commits and terminates PREPARED transactions.
  • If the ONE PHASE option is available, the preparation and submission are performed in the one-step end transaction.
  • XA ROLLBACK rolls back and terminates the transaction.
  • XA RECOVER displays information about all PREPARED transactions.

Let's look at the state transition of the XA transaction mentioned above.

XA START puts transactions in ACTIVE state. Once all statements are executed by an active transaction, an XA_END statement is issued, leaving the transaction in an IDLE state.

For IDLE transactions, XA PREPARE or XA COMMIT ONE PHASE can be issued.

XA PREPARE places transactions in the PREPARED state. XA COMMIT ONE PHASE prepares and submits transactions.

For PREPARED XA transactions, issue XA COMMIT to commit the end of the transaction.

Major improvements

Before 5.7.7, if the client connection terminates or the server exits normally, the PREPARED transaction is rolled back. When the client is Kill, all transactions are rolled back. Therefore, even if the XA transaction is in the PREPARED state, it cannot recover the transaction during the XA RECOVER period. Ideally, when the transaction is PREPARED, you should be able to COMMIT or ROLLBACK transactions. For this case, see the following examples:

mysql> CREATE TABLE t1(fld1 INT);
Query OK, 0 rows affected (0.01 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

mysql> XA START 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t1 VALUES (1);
Query OK, 1 row affected (0.00 sec)

mysql> XA END 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> XA PREPARE 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> Killed

Now start another client session. 

mysql> XA COMMIT 'test';
ERROR 1397 (XAE04): XAER_NOTA: Unknown XID

mysql> XA RECOVER;
Empty set (0.00 sec)

Also before 5.7.7, if the XA transaction is in the PREPARED state and the server abnormally exits, the transaction can be restarted after restarting the server - but it has not been replicated. After the server restarts, XA transactions still exist in the PREPARED state, but the content cannot be recorded in the binary log. Therefore, asynchronization of binary logs results in data drift. Therefore, XA cannot be used safely for replication.

ql> CREATE TABLE t1(fld1 INT);
Query OK, 0 rows affected (0.01 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

mysql> XA START 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t1 VALUES (1);
Query OK, 1 row affected (0.00 sec)

mysql> XA END 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> XA PREPARE 'test';
Query OK, 0 rows affected (0.00 sec)

Now kill the server.

mysql> XA RECOVER;

ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 1
Current database: test

+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
| 1        | 4            | 0            | test |
+----------+--------------+--------------+------+
1 row in set (0.02 sec)

mysql> XA COMMIT 'test';
Query OK, 0 rows affected (0.02 sec)

mysql> SHOW BINLOG EVENS\G;
*************************** 1. row ***************************
 Log_name: nisha-PORTEGE-Z30-A-bin.000001
 Pos: 4
 Event_type: Format_desc
 Server_id: 1
 End_log_pos: 120
 Info: Server ver: 5.6.29-debug-log, Binlog ver: 4
1 row in set (0.00 sec)

mysql> SELECT * FROM t1;
+------+
| fld1 |
+------+
| 1 |
+------+
1 row in set (0.00 sec)

To overcome these limitations, XA transaction recovery mechanism and binary logging mechanism need to be changed. This improvement was made in 5.7.7.

  • XA recovery mechanism has been extended. When the connection terminates, PREPARED XA transactions will remain in the transaction cache and be marked in InnoDB. This allows clients to resume PREPARED XA transactions, followed by COMMIT / ROLLBACK.
  • XA transactions now use two different GTIDs for binary recording in two phases, which allow transactions to interleave. In the first stage, when XA PREPARE is published, the transaction at that point is recorded in the binary log and can be identified by XA_prepare_log_event. In the second stage, when XA COMMIT/ROLLBACK is issued, the second part of the transaction is written to the binary log. Because XA PREPARE is persistent, XA transactions do not roll back and remain after server restart or client disconnection. The client can execute XA COMMIT / ROLLBACK and keep the binary log up to date. When the GTID is ON and the binary log is closed, the XA transaction can also work properly.

Let's look at the output of the above example after 5.7.7:

After the client disconnects:

l> CREATE TABLE t1(fld1 INT);
Query OK, 0 rows affected (0.01 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

mysql> XA START 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t1 VALUES (1); 
Query OK, 1 row affected (0.00 sec)

mysql> XA END 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> XA PREPARE 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> Killed

Now start another client session. 

mysql> XA RECOVER;
+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
|        1 |            4 |            0 | test |
+----------+--------------+--------------+------+
1 row in set (0.00 sec)

mysql> XA COMMIT 'test';
Query OK, 0 rows affected (0.02 sec) 

After the server restarts:

ql> CREATE TABLE t1(fld1 INT);
Query OK, 0 rows affected (0.01 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

mysql> XA START 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t1 VALUES (1);
Query OK, 1 row affected (0.00 sec)

mysql> XA END 'test';
Query OK, 0 rows affected (0.00 sec)

mysql> XA PREPARE 'test';
Query OK, 0 rows affected (0.00 sec)

Now kill the server.

mysql> XA RECOVER;

ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 1
Current database: test

+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
| 1        | 4            | 0            | test |
+----------+--------------+--------------+------+
1 row in set (0.02 sec)

mysql> XA COMMIT 'test';
Query OK, 0 rows affected (0.02 sec)

mysql> SHOW BINLOG events\G;
*************************** 3. row ***************************
 Log_name: nisha-PORTEGE-Z30-A-bin.000001
 Pos: 154
 Event_type: Anonymous_Gtid
 Server_id: 0
End_log_pos: 219
 Info: SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
*************************** 4. row ***************************
 Log_name: nisha-PORTEGE-Z30-A-bin.000001
 Pos: 219
 Event_type: Query
 Server_id: 0
End_log_pos: 319
 Info: XA START X'74657374',X'',1
*************************** 5. row ***************************
 Log_name: nisha-PORTEGE-Z30-A-bin.000001
 Pos: 319
 Event_type: Query
 Server_id: 0
End_log_pos: 418
 Info: use `test`; INSERT INTO t1 VALUES (1)
*************************** 6. row ***************************
 Log_name: nisha-PORTEGE-Z30-A-bin.000001
 Pos: 418
 Event_type: Query
 Server_id: 0
End_log_pos: 509
 Info: XA END X'74657374',X'',1
*************************** 7. row ***************************
 Log_name: nisha-PORTEGE-Z30-A-bin.000001
 Pos: 509
 Event_type: XA_prepare
 Server_id: 0
End_log_pos: 549
 Info: XA PREPARE X'74657374',X'',1
*************************** 8. row ***************************
   Log_name: nisha-PORTEGE-Z30-A-bin.000002
        Pos: 219
 Event_type: Query
  Server_id: 0
End_log_pos: 313
       Info: XA COMMIT X'74657374',X'',1
8 rows in set (0.00 sec)

conclusion

MySQL 5.7 has greatly improved XA support and made it possible to implement XA JOIN/XA RESUME operations. Expect to see its use in distributed systems.

Posted by SouThPaw09 on Tue, 10 Sep 2019 22:42:26 -0700