From 388296a1e6e57ee3efe737dbdf28e8d8bc6d12f6 Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 28 Sep 2023 19:06:59 +0300 Subject: [PATCH] MDEV-32257 dangling XA-rollback in binlog from emtpy XA in pseudo_slave_mode In `pseudo_slave_mode=1` aka "psedo-slave" mode any prepared XA transaction disconnects from the user session, as if the user connection drops. The xid of such transaction remains in the server, and should the prepared transaction be read-only, it is marked. The marking makes sure that the following termination of the read-only transaction ends up with ER_XA_RBROLLBACK. This did not take place actually for `pseudo_slave_mode=1` read-only. Fixed with checking the read-only status of a prepared transaction at time it disconnects from the `pseudo_slave_mode=1` session, to mark its xid when that's the case. --- .../suite/binlog/r/binlog_empty_xa_prepared.result | 8 ++++++++ .../suite/binlog/t/binlog_empty_xa_prepared.test | 12 ++++++++++++ sql/xa.cc | 5 +++++ 3 files changed, 25 insertions(+) diff --git a/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result b/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result index b11484367b8..4625a6cab21 100644 --- a/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result +++ b/mysql-test/suite/binlog/r/binlog_empty_xa_prepared.result @@ -217,3 +217,11 @@ master-bin.000001 # Gtid # # BEGIN GTID #-#-# master-bin.000001 # Query # # use `test`; INSERT INTO tm VALUES (1),(1) master-bin.000001 # Query # # COMMIT DROP TABLE tm; +connection default; +SET pseudo_slave_mode=1; +XA START 'a'; +XA END 'a'; +XA PREPARE 'a'; +XA ROLLBACK 'a'; +ERROR XA100: XA_RBROLLBACK: Transaction branch was rolled back +include/show_binlog_events.inc diff --git a/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test index 52b4ad2037b..501403f46fc 100644 --- a/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test +++ b/mysql-test/suite/binlog/t/binlog_empty_xa_prepared.test @@ -134,3 +134,15 @@ XA ROLLBACK '1'; --source include/show_binlog_events.inc DROP TABLE tm; + +# MDEV-32257 dangling XA-rollback in binlog from emtpy XA +--connection default +--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1) +--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1) +SET pseudo_slave_mode=1; +XA START 'a'; +XA END 'a'; +XA PREPARE 'a'; +--error ER_XA_RBROLLBACK +XA ROLLBACK 'a'; +--source include/show_binlog_events.inc diff --git a/sql/xa.cc b/sql/xa.cc index 52b9cf4c857..9df9da7acf1 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -1141,6 +1141,11 @@ static bool slave_applier_reset_xa_trans(THD *thd) ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); + if (thd->variables.pseudo_slave_mode && + !thd->transaction->all.is_trx_read_write()) + { + thd->transaction->xid_state.set_error(ER_XA_RBROLLBACK); + } thd->transaction->xid_state.xid_cache_element->acquired_to_recovered(); thd->transaction->xid_state.xid_cache_element= 0;