From 6a614d6934a85e8228957fe1d7242928a00dc5ff Mon Sep 17 00:00:00 2001 From: mkaruza Date: Wed, 21 Oct 2020 09:48:52 +0200 Subject: [PATCH] MDEV-22707: galera got stuck after flush tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deadlock is possible between applier thread and local committing thread with active FLUSH TABLE. Applier thread should skip table share checks and locks when opening table. Reviewed-by: Jan Lindström --- mysql-test/suite/galera/r/MDEV-22707.result | 26 +++++++++++ mysql-test/suite/galera/t/MDEV-22707.test | 51 +++++++++++++++++++++ sql/sql_base.cc | 5 ++ 3 files changed, 82 insertions(+) create mode 100644 mysql-test/suite/galera/r/MDEV-22707.result create mode 100644 mysql-test/suite/galera/t/MDEV-22707.test diff --git a/mysql-test/suite/galera/r/MDEV-22707.result b/mysql-test/suite/galera/r/MDEV-22707.result new file mode 100644 index 00000000000..a74844d7e12 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-22707.result @@ -0,0 +1,26 @@ +CREATE TABLE t1(f2 INT) ENGINE=InnoDB; +connect node_1_applier_thd, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb"; +connection node_2; +SET SESSION wsrep_sync_wait = 0; +INSERT INTO t1 (f2) VALUES (2); +connection node_1_applier_thd; +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +connection node_1; +SET SESSION wsrep_sync_wait = 0; +SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL wsrep_before_replication_reached WAIT_FOR continue'; +INSERT INTO t1 (f2) VALUES (1); +connect node_1_flush_thd, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET DEBUG_SYNC="now WAIT_FOR wsrep_before_replication_reached"; +SET GLOBAL debug_dbug = "+d,sync.wsrep_before_mdl_wait"; +FLUSH TABLES; +connect node_1_sync_release_thd, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET GLOBAL debug_dbug = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_before_mdl_wait"; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET DEBUG_SYNC = "now SIGNAL continue"; +SET DEBUG_SYNC = "RESET"; +connection node_1; +connection node_1_flush_thd; +connection node_2; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/MDEV-22707.test b/mysql-test/suite/galera/t/MDEV-22707.test new file mode 100644 index 00000000000..19755f7c5ac --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-22707.test @@ -0,0 +1,51 @@ +# +# MDEV-22707 galera got stuck after flush tables +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +CREATE TABLE t1(f2 INT) ENGINE=InnoDB; + +--connect node_1_applier_thd, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb"; + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; +--send INSERT INTO t1 (f2) VALUES (2) + +--connection node_1_applier_thd +# Wait for `sync.wsrep_apply_cb_reached` signal +SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; + +--connection node_1 +SET SESSION wsrep_sync_wait = 0; +SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL wsrep_before_replication_reached WAIT_FOR continue'; +--send INSERT INTO t1 (f2) VALUES (1) + +--connect node_1_flush_thd, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET DEBUG_SYNC="now WAIT_FOR wsrep_before_replication_reached"; +SET GLOBAL debug_dbug = "+d,sync.wsrep_before_mdl_wait"; +--send FLUSH TABLES + +--connect node_1_sync_release_thd, 127.0.0.1, root, , test, $NODE_MYPORT_1 +# First clear all DBUG points +SET GLOBAL debug_dbug = ""; +# Now signal threads to continue execution +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_before_mdl_wait"; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET DEBUG_SYNC = "now SIGNAL continue"; +SET DEBUG_SYNC = "RESET"; + +--connection node_1 +--reap + +--connection node_1_flush_thd +--reap + +--connection node_2 +--reap + +DROP TABLE t1; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index cc77b58cb3e..497c6a0322f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1859,7 +1859,12 @@ retry_share: DBUG_RETURN(FALSE); } +#ifdef WITH_WSREP + if (!((flags & MYSQL_OPEN_IGNORE_FLUSH) || + (wsrep_on(thd) && thd->wsrep_applier))) +#else if (!(flags & MYSQL_OPEN_IGNORE_FLUSH)) +#endif { if (share->tdc->flushed) {