MySQL Blog Archive
For the latest blogs go to blogs.oracle.com/mysql
Improvements to XA Support in MySQL 5.7

Introduction

XA stands for “eXtended Architecture”, and is a standard created by The Open Group for distributed transaction processing. While MySQL 5.0 was the first version to support XA, MySQL 5.7 has removed major limitations,  fixed a number of bugs, and increased overall test-case coverage.

Background

XA addresses the problem of preserving ACID properties within a single transaction across a distributed set of resources. The resources themselves could be other MySQL servers, or even different database technologies. The standard for XA describes the interaction between the global transaction manager and local resource manager.

As mentioned in the introduction, MySQL 5.0 introduced XA support, thus adding the ability to participate in global transactions. The XA support requires a resource manager which provides access to transactional resources and a transaction manager to coordinate the transactions within the global transaction. The XA implementation of MySQL enables the MySQL server to behave as a resource manager while the client  connecting to the MySQL server performs the tasks of a transaction manager.

XA uses two phase commit protocol where the first phase is the request for commit followed by the actual commit. Once the individual branches of the  global transaction have completed the execution, the two phase commit protocol kicks in:

  1. In the first phase, the transaction manager issues prepare for commit  message to all the branches involved in the global transaction. Before  the resource manager acknowledges that it is ready for commit, it records results of actions in a stable storage to perform the actual commit in the second phase.
  2. In the second phase, the transaction manager if it receives an affirmative response from all the branches involved, then they are notified to commit.  However if any of the branches replies negatively, all branches are notified to rollback.

The transaction manager interacts with multiple resource managers to handle the individual transaction/branches within the global transaction. The diagram depicts an XA transaction involving one resource manager. The statements for XA transaction begin with the XA keyword, action to be performed and an unique identifier. In the below example, the string ‘xatest’ represent the global transaction identifier. In addition to the global transaction identifier, a branch identifier and Format ID can be specified for the XA transaction.  The branch identifier is used to identify the local transaction and the format ID specifies the format used by the first two components.

xa1

XA START/BEGIN starts a transaction and defines its global transaction identifier.
XA END specifies the end of the active transaction.
XA PREPARE prepares the transaction for commit.
XA COMMIT [ONE PHASE] commits and terminates the transaction which was PREPARED.
In case of the ONE PHASE option, prepare and commit is performed in a single step ending transaction.
XA ROLLBACK rolls back and terminates the transaction.
XA RECOVER displays information about all the PREPARED transactions.

Let us look at the state transition for the above XA transaction.

Xa-diag
XA START puts the transaction in an ACTIVE state. Once all the statement are  executed by the active transaction, an XA_END statement is issued which puts the transaction in an IDLE state. For an IDLE transaction, either XA PREPARE or a XA COMMIT ONE PHASE can be issued. XA PREPARE puts the transaction in a PREPARED state.  However XA COMMIT ONE PHASE prepares and commits the transaction. For a PREPARED XA transaction, XA COMMIT is issued to commit  which ends the transaction.

Major Limitations are now lifted.

Prior to 5.7.7, a PREPARED transaction was rolled back if the client connection was terminated or when the server exited gracefully. When the client was killed, all the transactions were rolled back. Thus even though the XA transaction was in a PREPARED state, it could not recover the transaction during XA RECOVER. Ideally when a transaction is PREPARED, it should be possible to COMMIT or ROLLBACK the transaction. For this case,  let us look at the example which was reported in the bug 12161.

Also prior to 5.7.7,  if a XA transaction was in a PREPARED state and the server exited abnormally, the transaction could be resumed after restart of the server – but it was not replicated.  An XA transaction would still exist in the PREPARED state after server restart but the contents could not be logged in the binary log. Thus the binary log went out of sync causing data drift. Hence XA could not be used safely with replication.

Overcoming the above mentioned restrictions required changes in the XA transaction recovery mechanism and  binary logging mechanism.  This improvement was made in 5.7.7 through the implementation of work log number 7193 and 6860/ bug 12161.

  • The XA recovery mechansim has been extended such that when a connection is terminated, the PREPARED XA transactions are left in the transaction cache and marked specially in InnoDB. This allows the client to RECOVER the PREPARED XA transactions and then COMMIT/ ROLLBACK.
  • The XA transactions are now binlogged in two phases using two different GTIDs which allows the transactions to be interleaved.  During the first phase, when XA PREPARE is issued, the transaction up until that point is logged in the binary log and can be identified by XA_prepare_log_event. During the second phase, when XA COMMIT/ROLLBACK is issued, the second part of the transaction is written into the binary log. Since XA PREPARE is persistent,  the XA transaction is not rolled back and survives  the server restart or client disconnect. The client can perform XA COMMIT/ROLLBACK and the binary log remains up to date. XA transactions also works well when GTID is ON and binary log is turned OFF.

Let us look at the output of the above examples after 5.7.7:

After client disconnects:

After server restart:

Kudos to Andrei Elkin who implemented worklog 6860.  Also thanks to Guilhem Bichot, Marko Mäkelä, Luís Soares and the replication team members for their contribution to this worklog  through ideas, discussions and reviews.  Kudos to Dmitry Shulga for implementing the worklogs 7155 and 7193 which also supplemented the work for 6860.

Bugs Fixed and Improvements to Testcases

Here is the list of some of the bugs fixed in 5.7 to improve the overall XA support:

BUG #12161. XA recovery and client disconnection/BUG #75204: MYSQL/INNODB FORGETS PREPARED XA TRANSACTION ON RESTART. Both were fixed by the ‘support for replication’ as mentioned above.

BUG #78695: Fixed the assert triggered while a transaction is in the prepared state and the value of the internal server variable pseudo_slave_mode is modified.

BUG #78263: Fixed the assert triggered during XA COMMIT since the internal transaction state was not reset  between XA PREPARE and XA COMMIT/XA ROLLBACK as they constitute separate transactions under XA.

BUG #77392:   Fixed the issue where the slave group event parser did not recognize XA ROLLBACK as a boundary.

BUG #76734:  Fixed the assertion triggered during XA ROLLBACK for a read-only PREPARED transaction when the transaction body is empty and binlog enabled.

BUG #71352:  Fixed the issue where an XA START after server restart with the existing xid for a PREPARED XA transaction failed to commit during XA COMMIT.

BUG #47134: Fixed the issue where the server would exit if XA support was activated by multiple storage engines.

As can be seen bug Bug#79940 and Bug#76233 the XA support is not perfect yet, but we hope to get there!

The test suite has also been expanded to uncover any potentials problems and test the XA support. The test suites and its test scripts added/modified is listed below:

binlog_tests:  binlog_xa_prepared.test, gtid_next_xa.test.

binglog:  binlog_gtid_next_xa.test, binlog_xa_prepared_disconnect.test, binlog_xa_trx_gtid_response_packet.test, binlog_xa_handling.test

 rpl: rpl_gtids_table_disable_binlog_on_slave.test, rpl_trx_boundary_parser_warning.test, rpl_xa_survive_crash_debug.test, rpl_xa_survive_disconnect.test, rpl_xa_survive_disconnect_mixed_engines.test, rpl_trx_boundary_parser_warning.test

sys_vars: innodb_support_xa_func.test

mysql-test: xa.test, xa_prepared_binlog_off.test

Further Reading

More information about the XA standard is published by the open group and can be found here. Also the MySQL documentation is good source  for information about the XA support provided by MySQL.

Conclusion

The changes introduced in MySQL 5.7 improve support for XA dramatically and makes it possible to implement XA JOIN / XA RESUME operations.  We would be happy to hear from the community about the importance of extending MySQL to support these XA operations.  Feel free to leave a comment here. Meanwhile we look forward to seeing its usage in distributed systems.

As always, THANK YOU for using MySQL!

Save