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)) {