From 85bcc7d26315604a9cd67a64a0ad197dfcda93fc Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Tue, 19 Nov 2024 16:56:21 +0100 Subject: [PATCH] MDEV-35446 Sporadic failure of galera.galera_insert_multi Test failed sporadically when --ps-protocol was enabled: a transaction that was BF aborted on COMMIT would succeed instead of reporting the expected deadlock error. The reason for the failure was that, depending on timing, the transaction was BF aborted while the COMMIT statement was being prepared through a COM_STMT_PREPARE command. In the failing cases, the transaction was BF aborted after COM_STMT_PREPARE had already disabled the diagnostics area of the client. Attempt to override the deadlock error towards the end of dispatch_command() would be skipped, resulting in a successful COMMIT even if the transaction is aborted. This bug affected the following MTR tests: - galera_insert_multi - galera_nopk_unicode Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-35446.result | 22 ++++++++ mysql-test/suite/galera/t/MDEV-35446.cnf | 4 ++ mysql-test/suite/galera/t/MDEV-35446.test | 57 +++++++++++++++++++++ sql/sql_parse.cc | 7 ++- 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/MDEV-35446.result create mode 100644 mysql-test/suite/galera/t/MDEV-35446.cnf create mode 100644 mysql-test/suite/galera/t/MDEV-35446.test diff --git a/mysql-test/suite/galera/r/MDEV-35446.result b/mysql-test/suite/galera/r/MDEV-35446.result new file mode 100644 index 00000000000..30f3b2d591c --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-35446.result @@ -0,0 +1,22 @@ +connection node_2; +connection node_1; +connect bf_trx, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect victim_trx, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_2_ctrl, 127.0.0.1, root, , test, $NODE_MYPORT_2; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection victim_trx; +START TRANSACTION; +INSERT INTO t1 VALUES (2), (1); +connection node_2_ctrl; +SET GLOBAL debug_dbug = '+d,sync.wsrep_apply_cb'; +connection bf_trx; +INSERT INTO t1 VALUES (1), (2); +connection node_2_ctrl; +SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +SET GLOBAL debug_dbug = ''; +connection victim_trx; +SET DEBUG_SYNC = "wsrep_at_dispatch_end_before_result SIGNAL signal.wsrep_apply_cb WAIT_FOR bf_abort"; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/MDEV-35446.cnf b/mysql-test/suite/galera/t/MDEV-35446.cnf new file mode 100644 index 00000000000..ee365a18340 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-35446.cnf @@ -0,0 +1,4 @@ +!include ../galera_2nodes.cnf + +[mysqltest] +ps-protocol diff --git a/mysql-test/suite/galera/t/MDEV-35446.test b/mysql-test/suite/galera/t/MDEV-35446.test new file mode 100644 index 00000000000..49b82adcd01 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-35446.test @@ -0,0 +1,57 @@ +# +# MDEV-35446 +# +# Test BF abort of a transaction under PS protocol, after +# a statement is prepared (and the diagnostics area is +# disabled). +# + +--source include/have_debug_sync.inc +--source include/galera_cluster.inc + +# +# Setup: bf_trx executes in node_1 and will BF abort victim_trx. +# +--connect bf_trx, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connect victim_trx, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_2_ctrl, 127.0.0.1, root, , test, $NODE_MYPORT_2 + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection victim_trx +START TRANSACTION; +INSERT INTO t1 VALUES (2), (1); + +--connection node_2_ctrl +SET GLOBAL debug_dbug = '+d,sync.wsrep_apply_cb'; + +--connection bf_trx +INSERT INTO t1 VALUES (1), (2); + +--connection node_2_ctrl +SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +SET GLOBAL debug_dbug = ''; + +# +# COMMIT the victim_trx and expect a deadlock error. +# Here we park the client in a sync point at the end of prepare +# command (COM_STMT_PREPARE), where the diagnostics area of the +# client has already been disabled. The client signals the +# applier to continue and will be BF aborted. +# If bug is present, the transaction is aborted, but the COMMIT +# statement succeeds (instead of returning deadlock error). +# +--connection victim_trx + +--disable_ps_protocol +SET DEBUG_SYNC = "wsrep_at_dispatch_end_before_result SIGNAL signal.wsrep_apply_cb WAIT_FOR bf_abort"; +--enable_ps_protocol + +--error ER_LOCK_DEADLOCK +COMMIT; + +# +# Cleanup +# +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0ed938eb63e..e7699a3f464 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1165,7 +1165,8 @@ static bool wsrep_command_no_result(char command) { return (command == COM_STMT_FETCH || command == COM_STMT_SEND_LONG_DATA || - command == COM_STMT_CLOSE); + command == COM_STMT_CLOSE || + command == COM_STMT_PREPARE); } #endif /* WITH_WSREP */ #ifndef EMBEDDED_LIBRARY @@ -2439,6 +2440,10 @@ dispatch_end: { WSREP_DEBUG("THD is killed at dispatch_end"); } + if (thd->lex->sql_command != SQLCOM_SET_OPTION) + { + DEBUG_SYNC(thd, "wsrep_at_dispatch_end_before_result"); + } wsrep_after_command_before_result(thd); if (wsrep_current_error(thd) && !wsrep_command_no_result(command)) {