diff --git a/mysql-test/main/flush.result b/mysql-test/main/flush.result index 901f4bcd315..39e0b9432fe 100644 --- a/mysql-test/main/flush.result +++ b/mysql-test/main/flush.result @@ -329,12 +329,9 @@ flush tables t1 with read lock; handler t1 read a next; ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction unlock tables; -# -# Sic: lost handler position. -# handler t1 read a next; a -1 +3 handler t1 close; drop table t1; # diff --git a/mysql-test/main/flush.test b/mysql-test/main/flush.test index b51a9682dff..6d76196bf54 100644 --- a/mysql-test/main/flush.test +++ b/mysql-test/main/flush.test @@ -412,9 +412,6 @@ flush tables t1 with read lock; --error ER_LOCK_OR_ACTIVE_TRANSACTION handler t1 read a next; unlock tables; ---echo # ---echo # Sic: lost handler position. ---echo # handler t1 read a next; handler t1 close; drop table t1; diff --git a/mysql-test/main/mdl_sync.result b/mysql-test/main/mdl_sync.result index 5203fdddb2d..0ffe2f745a0 100644 --- a/mysql-test/main/mdl_sync.result +++ b/mysql-test/main/mdl_sync.result @@ -2010,117 +2010,6 @@ connection deadlock_con1; connection default; # Reaping ALTER. It should succeed and not produce ER_LOCK_DEADLOCK. drop table t1; -# -# Now, test for a situation in which deadlock involves waiting not -# only in MDL subsystem but also for TDC. Such deadlocks should be -# successfully detected. If possible, they should be resolved without -# resorting to ER_LOCK_DEADLOCK error. -# -create table t1(i int); -create table t2(j int); -# -# First, let us check how we handle a simple scenario involving -# waits in MDL and TDC. -# -set debug_sync= 'RESET'; -connection deadlock_con1; -# Start a statement, which will acquire SR metadata lock on t1, open it -# and then stop, before trying to acquire SW lock on t2 and opening it. -set debug_sync='open_tables_after_open_and_process_table SIGNAL parked WAIT_FOR go'; -# Sending: -select * from t1 where i in (select j from t2 for update); -connection deadlock_con2; -# Wait till the above SELECT stops. -set debug_sync='now WAIT_FOR parked'; -# The below FLUSH TABLES WITH READ LOCK should acquire -# SNW locks on t1 and t2 and wait till SELECT closes t1. -# Sending: -flush tables t1, t2 with read lock; -connection deadlock_con3; -# Wait until FLUSH TABLES WITH t1, t2 READ LOCK starts waiting -# for SELECT to close t1. -# Resume SELECT, so it tries to acquire SW lock on t1 and blocks, -# creating a deadlock. This deadlock should be detected and resolved -# by backing-off SELECT. As a result FTWRL should be able to finish. -set debug_sync='now SIGNAL go'; -connection deadlock_con2; -# Reap FLUSH TABLES WITH READ LOCK. -unlock tables; -connection deadlock_con1; -# Reap SELECT. -i -# -# The same scenario with a slightly different order of events -# which emphasizes that setting correct deadlock detector weights -# for flush waits is important. -# -set debug_sync= 'RESET'; -connection deadlock_con2; -set debug_sync='flush_tables_with_read_lock_after_acquire_locks SIGNAL parked WAIT_FOR go'; -# The below FLUSH TABLES WITH READ LOCK should acquire -# SNW locks on t1 and t2 and wait on debug sync point. -# Sending: -flush tables t1, t2 with read lock; -connection deadlock_con1; -# Wait till FLUSH TABLE WITH READ LOCK stops. -set debug_sync='now WAIT_FOR parked'; -# Start statement which will acquire SR metadata lock on t1, open -# it and then will block while trying to acquire SW lock on t2. -# Sending: -select * from t1 where i in (select j from t2 for update); -connection deadlock_con3; -# Wait till the above SELECT blocks. -# Resume FLUSH TABLES, so it tries to flush t1, thus creating -# a deadlock. This deadlock should be detected and resolved by -# backing-off SELECT. As a result FTWRL should be able to finish. -set debug_sync='now SIGNAL go'; -connection deadlock_con2; -# Reap FLUSH TABLES WITH READ LOCK. -unlock tables; -connection deadlock_con1; -# Reap SELECT. -i -# -# Now a more complex scenario involving two connections -# waiting for MDL and one for TDC. -# -set debug_sync= 'RESET'; -connection deadlock_con1; -# Start a statement which will acquire SR metadata lock on t2, open it -# and then stop, before trying to acquire SR on t1 and opening it. -set debug_sync='open_tables_after_open_and_process_table SIGNAL parked WAIT_FOR go'; -# Sending: -select * from t2, t1; -connection deadlock_con2; -# Wait till the above SELECT stops. -set debug_sync='now WAIT_FOR parked'; -# The below FLUSH TABLES WITH READ LOCK should acquire -# SNW locks on t2 and wait till SELECT closes t2. -# Sending: -flush tables t2 with read lock; -connection deadlock_con3; -# Wait until FLUSH TABLES WITH READ LOCK starts waiting -# for SELECT to close t2. -# The below DROP TABLES should acquire X lock on t1 and start -# waiting for X lock on t2. -# Sending: -drop tables t1, t2; -connection default; -# Wait until DROP TABLES starts waiting for X lock on t2. -# Resume SELECT, so it tries to acquire SR lock on t1 and blocks, -# creating a deadlock. This deadlock should be detected and resolved -# by backing-off SELECT. As a result, FTWRL should be able to finish. -set debug_sync='now SIGNAL go'; -connection deadlock_con2; -# Reap FLUSH TABLES WITH READ LOCK. -# Unblock DROP TABLES. -unlock tables; -connection deadlock_con3; -# Reap DROP TABLES. -connection deadlock_con1; -# Reap SELECT. It should emit error about missing table. -ERROR 42S02: Table 'test.t2' doesn't exist -connection default; set debug_sync= 'RESET'; disconnect deadlock_con1; disconnect deadlock_con2; diff --git a/mysql-test/main/mdl_sync.test b/mysql-test/main/mdl_sync.test index 2a1e488ab44..557fbe261a2 100644 --- a/mysql-test/main/mdl_sync.test +++ b/mysql-test/main/mdl_sync.test @@ -2493,170 +2493,6 @@ connection default; drop table t1; ---echo # ---echo # Now, test for a situation in which deadlock involves waiting not ---echo # only in MDL subsystem but also for TDC. Such deadlocks should be ---echo # successfully detected. If possible, they should be resolved without ---echo # resorting to ER_LOCK_DEADLOCK error. ---echo # -create table t1(i int); -create table t2(j int); - ---echo # ---echo # First, let us check how we handle a simple scenario involving ---echo # waits in MDL and TDC. ---echo # -set debug_sync= 'RESET'; - -connection deadlock_con1; ---echo # Start a statement, which will acquire SR metadata lock on t1, open it ---echo # and then stop, before trying to acquire SW lock on t2 and opening it. -set debug_sync='open_tables_after_open_and_process_table SIGNAL parked WAIT_FOR go'; ---echo # Sending: ---send select * from t1 where i in (select j from t2 for update) - -connection deadlock_con2; ---echo # Wait till the above SELECT stops. -set debug_sync='now WAIT_FOR parked'; ---echo # The below FLUSH TABLES WITH READ LOCK should acquire ---echo # SNW locks on t1 and t2 and wait till SELECT closes t1. ---echo # Sending: -send flush tables t1, t2 with read lock; - -connection deadlock_con3; ---echo # Wait until FLUSH TABLES WITH t1, t2 READ LOCK starts waiting ---echo # for SELECT to close t1. -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" and - info = "flush tables t1, t2 with read lock"; ---source include/wait_condition.inc - ---echo # Resume SELECT, so it tries to acquire SW lock on t1 and blocks, ---echo # creating a deadlock. This deadlock should be detected and resolved ---echo # by backing-off SELECT. As a result FTWRL should be able to finish. -set debug_sync='now SIGNAL go'; - -connection deadlock_con2; ---echo # Reap FLUSH TABLES WITH READ LOCK. -reap; -unlock tables; - -connection deadlock_con1; ---echo # Reap SELECT. -reap; - ---echo # ---echo # The same scenario with a slightly different order of events ---echo # which emphasizes that setting correct deadlock detector weights ---echo # for flush waits is important. ---echo # -set debug_sync= 'RESET'; - -connection deadlock_con2; -set debug_sync='flush_tables_with_read_lock_after_acquire_locks SIGNAL parked WAIT_FOR go'; - ---echo # The below FLUSH TABLES WITH READ LOCK should acquire ---echo # SNW locks on t1 and t2 and wait on debug sync point. ---echo # Sending: -send flush tables t1, t2 with read lock; - -connection deadlock_con1; ---echo # Wait till FLUSH TABLE WITH READ LOCK stops. -set debug_sync='now WAIT_FOR parked'; - ---echo # Start statement which will acquire SR metadata lock on t1, open ---echo # it and then will block while trying to acquire SW lock on t2. ---echo # Sending: -send select * from t1 where i in (select j from t2 for update); - -connection deadlock_con3; ---echo # Wait till the above SELECT blocks. -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table metadata lock" and - info = "select * from t1 where i in (select j from t2 for update)"; ---source include/wait_condition.inc - ---echo # Resume FLUSH TABLES, so it tries to flush t1, thus creating ---echo # a deadlock. This deadlock should be detected and resolved by ---echo # backing-off SELECT. As a result FTWRL should be able to finish. -set debug_sync='now SIGNAL go'; - -connection deadlock_con2; ---echo # Reap FLUSH TABLES WITH READ LOCK. -reap; -unlock tables; - -connection deadlock_con1; ---echo # Reap SELECT. -reap; - ---echo # ---echo # Now a more complex scenario involving two connections ---echo # waiting for MDL and one for TDC. ---echo # -set debug_sync= 'RESET'; - -connection deadlock_con1; ---echo # Start a statement which will acquire SR metadata lock on t2, open it ---echo # and then stop, before trying to acquire SR on t1 and opening it. -set debug_sync='open_tables_after_open_and_process_table SIGNAL parked WAIT_FOR go'; ---echo # Sending: -send select * from t2, t1; - -connection deadlock_con2; ---echo # Wait till the above SELECT stops. -set debug_sync='now WAIT_FOR parked'; ---echo # The below FLUSH TABLES WITH READ LOCK should acquire ---echo # SNW locks on t2 and wait till SELECT closes t2. ---echo # Sending: -send flush tables t2 with read lock; - -connection deadlock_con3; ---echo # Wait until FLUSH TABLES WITH READ LOCK starts waiting ---echo # for SELECT to close t2. -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" and - info = "flush tables t2 with read lock"; ---source include/wait_condition.inc - ---echo # The below DROP TABLES should acquire X lock on t1 and start ---echo # waiting for X lock on t2. ---echo # Sending: -send drop tables t1, t2; - -connection default; ---echo # Wait until DROP TABLES starts waiting for X lock on t2. -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table metadata lock" and - info = "drop tables t1, t2"; ---source include/wait_condition.inc - ---echo # Resume SELECT, so it tries to acquire SR lock on t1 and blocks, ---echo # creating a deadlock. This deadlock should be detected and resolved ---echo # by backing-off SELECT. As a result, FTWRL should be able to finish. -set debug_sync='now SIGNAL go'; - -connection deadlock_con2; ---echo # Reap FLUSH TABLES WITH READ LOCK. -reap; ---echo # Unblock DROP TABLES. -unlock tables; - -connection deadlock_con3; ---echo # Reap DROP TABLES. -reap; - -connection deadlock_con1; ---echo # Reap SELECT. It should emit error about missing table. ---error ER_NO_SUCH_TABLE -reap; - -connection default; - set debug_sync= 'RESET'; disconnect deadlock_con1; diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index 63b233faea6..ce49378204d 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -512,7 +512,6 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) { Lock_tables_prelocking_strategy lock_tables_prelocking_strategy; - TABLE_LIST *table_list; /* This is called from SQLCOM_FLUSH, the transaction has @@ -545,16 +544,10 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) DEBUG_SYNC(thd,"flush_tables_with_read_lock_after_acquire_locks"); - for (table_list= all_tables; table_list; + /* Reset ticket to satisfy asserts in open_tables(). */ + for (auto table_list= all_tables; table_list; table_list= table_list->next_global) - { - /* Request removal of table from cache. */ - tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED, - table_list->db.str, - table_list->table_name.str); - /* Reset ticket to satisfy asserts in open_tables(). */ table_list->mdl_request.ticket= NULL; - } } thd->variables.option_bits|= OPTION_TABLE_LOCK; @@ -589,6 +582,16 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) } } + if (thd->lex->type & REFRESH_READ_LOCK) + { + for (auto table_list= all_tables; table_list; + table_list= table_list->next_global) + { + if (table_list->table->file->extra(HA_EXTRA_FLUSH)) + goto error_reset_bits; + } + } + if (thd->locked_tables_list.init_locked_tables(thd)) goto error_reset_bits;