summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2022-12-10 14:25:55 +0300
committerAleksey Midenkov <midenok@gmail.com>2023-01-17 12:34:44 +0300
commit8022a6fff7bd0dca33ed23d13a2a02e8b1080434 (patch)
tree1d2b3c883072c21bea9d2717366a8ec40f3ebafa
parent6f17c5a6c4be698b5f86debfa1855176931dae6a (diff)
downloadmariadb-git-8022a6fff7bd0dca33ed23d13a2a02e8b1080434.tar.gz
MDEV-29824 Galera crashes when running CoR for a locked table
locked_tables_list.reopen_tables() does external_lock() which in InnoDB opens new transaction. The previous commit in send_eof() sets s_committed state in wsrep. The new transaction didn't change that state yet and on commit s_committed state is unexpected. The fix is similar to MDEV-22222 (2b8b7394a12): we update wsrep state before starting new transaction. The better wsrep fix would track the state properly when the new transaction is started.
-rw-r--r--mysql-test/suite/galera/r/create.result9
-rw-r--r--mysql-test/suite/galera/t/create.test10
-rw-r--r--sql/sql_table.cc17
3 files changed, 36 insertions, 0 deletions
diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result
index cd0380b206d..b434052727f 100644
--- a/mysql-test/suite/galera/r/create.result
+++ b/mysql-test/suite/galera/r/create.result
@@ -91,6 +91,15 @@ c1
SELECT * FROM t2;
c1
DROP TABLE t1, t2;
+#
+# MDEV-29824 Galera crashes when running CoR for a locked table
+#
+connection node_1;
+SET autocommit=0;
+CREATE TABLE t0 (x INT,y INT);
+LOCK TABLES t0 WRITE;
+CREATE OR REPLACE TABLE t0 SELECT 1;
+DROP TABLE t0;
disconnect node_2;
disconnect node_1;
# End of tests
diff --git a/mysql-test/suite/galera/t/create.test b/mysql-test/suite/galera/t/create.test
index 96a6640c21f..7ebee7e2e47 100644
--- a/mysql-test/suite/galera/t/create.test
+++ b/mysql-test/suite/galera/t/create.test
@@ -84,6 +84,16 @@ SELECT * FROM t2;
# Cleanup
DROP TABLE t1, t2;
+--echo #
+--echo # MDEV-29824 Galera crashes when running CoR for a locked table
+--echo #
+--connection node_1
+SET autocommit=0;
+CREATE TABLE t0 (x INT,y INT);
+LOCK TABLES t0 WRITE;
+CREATE OR REPLACE TABLE t0 SELECT 1;
+DROP TABLE t0;
+
--source include/galera_end.inc
--echo # End of tests
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 4905bb18801..cbe0707ec83 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -60,6 +60,9 @@
#include "debug.h" // debug_crash_here()
#include <algorithm>
#include "wsrep_mysqld.h"
+#ifdef WITH_WSREP
+#include "wsrep_trans_observer.h" /* wsrep transaction hooks */
+#endif
#include "rpl_mi.h"
#include "rpl_rli.h"
#include "log.h"
@@ -4627,6 +4630,20 @@ bool HA_CREATE_INFO::finalize_locked_tables(THD *thd, bool operation_failed)
DBUG_ASSERT(pos_in_locked_tables);
DBUG_ASSERT(thd->locked_tables_mode);
DBUG_ASSERT(thd->variables.option_bits & OPTION_TABLE_LOCK);
+
+#ifdef WITH_WSREP
+ /*
+ finalize_locked_tables() is done after commit. Cleanup wsrep transaction
+ state (s_committed) before reopen_tables() starts new transaction.
+ */
+ if (WSREP_NNULL(thd) && wsrep_thd_is_local(thd) &&
+ wsrep_after_statement(thd))
+ {
+ thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
+ return true;
+ }
+#endif
+
if (!operation_failed)
{
/*