Bug #71352 xa start with the exist xid, and then xa commit with the xid will failed
| Submitted: | 12 Jan 2014 4:03 | Modified: | 20 May 2014 0:34 |
|---|---|---|---|
| Reporter: | HongXiang Jiang (OCA) | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: XA transactions | Severity: | S3 (Non-critical) |
| Version: | 5.5.35, 5.6.14 | OS: | Linux |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | server crash, xa start | ||
[13 Jan 2014 9:44]
MySQL Verification Team
Hello Boyce, Thank you for the bug report and test case. Verified as described. Thanks, Umesh
[13 Jan 2014 9:50]
MySQL Verification Team
// 5.5.35 mysql> select version(); +------------------+ | version() | +------------------+ | 5.5.35-debug-log | +------------------+ 1 row in set (0.00 sec) mysql> mysql> create table t(id int)engine=innodb; Query OK, 0 rows affected (0.04 sec) mysql> xa start '111'; Query OK, 0 rows affected (0.00 sec) mysql> insert into t values(1); Query OK, 1 row affected (0.00 sec) mysql> xa end '111'; Query OK, 0 rows affected (0.00 sec) mysql> xa prepare '111'; Query OK, 0 rows affected (0.00 sec) mysql> xa recover; +----------+--------------+--------------+------+ | formatID | gtrid_length | bqual_length | data | +----------+--------------+--------------+------+ | 1 | 3 | 0 | 111 | +----------+--------------+--------------+------+ 1 row in set (0.00 sec) // Killed mysqld from other session mysql> mysql> xa start '111'; ERROR 1440 (XAE08): XAER_DUPID: The XID already exists mysql> xa recover; +----------+--------------+--------------+------+ | formatID | gtrid_length | bqual_length | data | +----------+--------------+--------------+------+ | 1 | 3 | 0 | 111 | +----------+--------------+--------------+------+ 1 row in set (0.00 sec) mysql> xa commit '111'; ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the NON-EXISTING state mysql> xa rollback '111'; ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the NON-EXISTING state
[20 May 2014 0:34]
Paul DuBois
Noted in 5.7.5 changelog. XA START after a server restart with the exising XID followed by XA COMMIT failed to commit.
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.042 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
Description: when a xa transaction is prepared and the server crashed, then restart the MySQL server, first, do xa start with the exist xid, says: XAER_DUPID: The XID already exists, that's OK, but do xa commit with this xid, says that:XAER_RMFAIL: The command cannot be executed when global transaction is in the NON-EXISTING state. the prepared transaction can't be committed. the reason is: in the code transaction.cc::trans_xa_start thd->transaction.xid_state.xid.set(thd->lex->xid); if (xid_cache_insert(&thd->transaction.xid_state)) { thd->transaction.xid_state.xa_state= XA_NOTR; thd->transaction.xid_state.xid.null(); trans_rollback(thd); DBUG_RETURN(true); } first, set the xid, then, if insert failed, set the xid null, in the function null(), only set the formatID = -1, not clear the data. but in the transaction.cc::trans_xa_commit if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) the code above use xid.eq() to compare the two xids, in the function xid.eq(), only compared with gtrid_length, bqual_length and data, do not contain the formatID, so after do trans_xa_start, the gtrid_length, bqual_length and data have been setted with the formatID = -1, and then do trans_xa_commit, the xid.eq() return true, it's wrong! How to repeat: mysql> create table t(id int)engine=innodb; Query OK, 0 rows affected (0.01 sec) mysql> xa start '111'; Query OK, 0 rows affected (0.00 sec) mysql> insert into t values(1); Query OK, 1 row affected (0.00 sec) mysql> xa end '111'; Query OK, 0 rows affected (0.00 sec) mysql> xa prepare '111'; Query OK, 0 rows affected (0.00 sec) kill -9 mysqld restart mysqld mysql> xa start '111'; ERROR 1440 (XAE08): XAER_DUPID: The XID already exists mysql> xa commit '111'; ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the NON-EXISTING state Suggested fix: xid.eq() not only compare with gtrid_length, bqual_length and data, but also with formatID. In the trans_xa_start, if insert failed, clear the xid's data