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.
This commit is contained in:
Andrei 2023-09-28 19:06:59 +03:00
parent 29e7f53bf5
commit 388296a1e6
3 changed files with 25 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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;