diff --git a/mysql-test/main/flush_read_lock.result b/mysql-test/main/flush_read_lock.result index 5e836dd0544..f74937cb304 100644 --- a/mysql-test/main/flush_read_lock.result +++ b/mysql-test/main/flush_read_lock.result @@ -1677,6 +1677,8 @@ set global sql_mode=default; # Deadlock between FTWRL under open handler and DDL/LOCK TABLES # CREATE TABLE t1(a INT); +# +connect con3,localhost,root,,; HANDLER t1 OPEN; # connect con1,localhost,root,,; @@ -1692,7 +1694,10 @@ disconnect con2; connection default; FLUSH TABLES WITH READ LOCK; UNLOCK TABLES; +# +connection con3; HANDLER t1 CLOSE; +disconnect con3; # connection con1; UNLOCK TABLES; @@ -1727,3 +1732,31 @@ disconnect con1; connection default; DROP TABLE t1; SET DEBUG_SYNC= 'RESET'; +# +# MDEV-19384 Deadlock between FTWRL under open HANDLER, LOCK TABLE +# and DROP DATABASE +# +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.t1(a INT); +HANDLER mysqltest.t1 OPEN as t1; +connect con1,localhost,root,,; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +LOCK TABLE mysqltest.t1 WRITE; +connect con2,localhost,root,,; +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +DROP DATABASE mysqltest; +connect con3,localhost,root,,; +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +disconnect con3; +connection default; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +HANDLER t1 CLOSE; +connection con1; +UNLOCK TABLES; +disconnect con1; +connection con2; +disconnect con2; +connection default; +SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/main/flush_read_lock.test b/mysql-test/main/flush_read_lock.test index 786c1747c20..f537339ad6c 100644 --- a/mysql-test/main/flush_read_lock.test +++ b/mysql-test/main/flush_read_lock.test @@ -2023,6 +2023,9 @@ set global sql_mode=default; --echo # Deadlock between FTWRL under open handler and DDL/LOCK TABLES --echo # CREATE TABLE t1(a INT); + +--echo # +connect (con3,localhost,root,,); HANDLER t1 OPEN; --echo # @@ -2041,7 +2044,11 @@ disconnect con2; connection default; FLUSH TABLES WITH READ LOCK; UNLOCK TABLES; + +--echo # +connection con3; HANDLER t1 CLOSE; +disconnect con3; --echo # connection con1; @@ -2087,3 +2094,40 @@ disconnect con1; connection default; DROP TABLE t1; SET DEBUG_SYNC= 'RESET'; + +--echo # +--echo # MDEV-19384 Deadlock between FTWRL under open HANDLER, LOCK TABLE +--echo # and DROP DATABASE +--echo # + +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.t1(a INT); +HANDLER mysqltest.t1 OPEN as t1; + +connect (con1,localhost,root,,); +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +--send LOCK TABLE mysqltest.t1 WRITE +connect (con2,localhost,root,,); +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +--send DROP DATABASE mysqltest + +connect (con3,localhost,root,,); +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +disconnect con3; + +connection default; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +HANDLER t1 CLOSE; +connection con1; + +--error 0,ER_NO_SUCH_TABLE +reap; +UNLOCK TABLES; +disconnect con1; +connection con2; +reap; +disconnect con2; +connection default; +SET DEBUG_SYNC= 'RESET'; diff --git a/sql/lock.cc b/sql/lock.cc index d53aad5a2ba..596e77b23e3 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1029,6 +1029,12 @@ bool Global_read_lock::lock_global_read_lock(THD *thd) DBUG_RETURN(1); } + /* + Release HANDLER OPEN by the current THD as they may cause deadlocks + if another thread is trying to simultaneous drop the table + */ + mysql_ha_cleanup_no_free(thd); + DBUG_ASSERT(! thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "", MDL_BACKUP_FTWRL1)); DBUG_ASSERT(! thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "", @@ -1050,9 +1056,6 @@ bool Global_read_lock::lock_global_read_lock(THD *thd) m_mdl_global_read_lock= mdl_request.ticket; m_state= GRL_ACQUIRED; - - /* Release HANDLER OPEN after we have got our MDL lock */ - mysql_ha_cleanup_no_free(thd); } /* We DON'T set global_read_lock_blocks_commit now, it will be set after