# # We need the Debug Sync Facility. # --source include/have_debug_sync.inc # We need InnoDB tables for some of the tests. --source include/have_innodb.inc # Save the initial number of concurrent sessions. --source include/count_sessions.inc # Clean up resources used in this test case. --disable_warnings SET DEBUG_SYNC= 'RESET'; --enable_warnings # # Test the case of when a exclusive lock request waits for a # shared lock being upgraded to a exclusive lock. # connect (con1,localhost,root,,test,,); connect (con2,localhost,root,,test,,); connect (con3,localhost,root,,test,,); connection default; --disable_warnings drop table if exists t1,t2,t3; --enable_warnings create table t1 (i int); create table t2 (i int); --echo connection: default lock tables t2 read; connection con1; --echo connection: con1 set debug_sync='mdl_upgrade_lock SIGNAL parked WAIT_FOR go'; --send alter table t1 rename t3 connection default; --echo connection: default set debug_sync= 'now WAIT_FOR parked'; connection con2; --echo connection: con2 set debug_sync='mdl_acquire_lock_wait SIGNAL go'; --send drop table t1,t2 connection con1; --echo connection: con1 --reap connection default; --echo connection: default unlock tables; connection con2; --echo connection: con2 --error ER_BAD_TABLE_ERROR --reap connection default; drop table t3; disconnect con1; disconnect con2; disconnect con3; # Clean up resources used in this test case. --disable_warnings SET DEBUG_SYNC= 'RESET'; --enable_warnings --echo # --echo # Basic test coverage for type-of-operation aware metadata locks. --echo # --disable_warnings drop table if exists t1, t2, t3; --enable_warnings connect(mdl_con1,localhost,root,,); connect(mdl_con2,localhost,root,,); connect(mdl_con3,localhost,root,,); connection default; set debug_sync= 'RESET'; create table t1 (c1 int); --echo # --echo # A) First let us check compatibility rules between differend kinds of --echo # type-of-operation aware metadata locks. --echo # Of course, these rules are already covered by the tests scattered --echo # across the test suite. But it still makes sense to have one place --echo # which covers all of them. --echo # --echo # 1) Acquire S (simple shared) lock on the table (by using HANDLER): --echo # handler t1 open; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that S, SH, SR, SW and SWLP locks are compatible with it. handler t1 open t; handler t close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; insert into t1 values (1); insert low_priority into t1 values (1); --echo # Check that SU lock is compatible with it. To do this use ALTER TABLE --echo # which will fail when constructing .frm and thus obtaining SU metadata --echo # lock. --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # Check that SRO lock is compatible with S lock. lock table t1 read; select count(*) from t1; unlock tables; --echo # Check that SNW lock is compatible with it. To do this use ALTER TABLE --echo # which will fail during copying the table and thus obtaining SNW metadata --echo # lock. --error ER_DUP_ENTRY alter table t1 add primary key (c1); --echo # Check that SNRW lock is compatible with S lock. lock table t1 write; insert into t1 values (1); unlock tables; --echo # Check that X lock is incompatible with S lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above RENAME is blocked because of S lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Unblock RENAME TABLE. handler t1 close; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME TABLE. --reap --echo # Restore the original state of the things. rename table t2 to t1; --echo # --echo # Switching to connection 'default'. connection default; handler t1 open; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that upgrade from SNW to X is blocked by presence of S lock. --echo # Sending: --send alter table t1 add column c2 int; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above ALTER TABLE is blocked because of S lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column c2 int"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Unblock ALTER TABLE. handler t1 close; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --reap --echo # Restore the original state of the things. alter table t1 drop column c2; --echo # --echo # Switching to connection 'default'. connection default; handler t1 open; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that upgrade from SNRW to X is blocked by presence of S lock. lock table t1 write; --echo # Sending: --send alter table t1 add column c2 int; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above upgrade of SNRW to X in ALTER TABLE is blocked --echo # because of S lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column c2 int"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Unblock ALTER TABLE. handler t1 close; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --reap --echo # Restore the original state of the things. alter table t1 drop column c2; unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # 2) Acquire SH (shared high-priority) lock on the table. --echo # We have to involve DEBUG_SYNC facility for this as usually --echo # such kind of locks are short-lived. --echo # set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send select table_name, table_type, auto_increment, table_comment from information_schema.tables where table_schema='test' and table_name='t1'; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that S, SH, SR, SW and SWLP locks are compatible with it. handler t1 open; handler t1 close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; insert into t1 values (1), (1); delete low_priority from t1 limit 1; --echo # Check that SU lock is compatible with it. To do this use ALTER TABLE --echo # which will fail when constructing .frm and thus obtaining SU metadata --echo # lock. --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # Check that SRO lock is compatible with SH lock. lock table t1 read; select count(*) from t1; unlock tables; --echo # Check that SNW lock is compatible with it. To do this use ALTER TABLE --echo # which will fail during copying the table and thus obtaining SNW metadata --echo # lock. --error ER_DUP_ENTRY alter table t1 add primary key (c1); --echo # Check that SNRW lock is compatible with SH lock. lock table t1 write; delete from t1 limit 1; unlock tables; --echo # Check that X lock is incompatible with SH lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above RENAME is blocked because of SH lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping SELECT ... FROM I_S. --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME TABLE. --reap --echo # Restore the original state of the things. rename table t2 to t1; --echo # --echo # Switching to connection 'default'. connection default; set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send select table_name, table_type, auto_increment, table_comment from information_schema.tables where table_schema='test' and table_name='t1'; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that upgrade from SNW to X is blocked by presence of SH lock. --echo # Sending: --send alter table t1 add column c2 int; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above ALTER TABLE is blocked because of SH lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column c2 int"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping SELECT ... FROM I_S. --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --reap --echo # Restore the original state of the things. alter table t1 drop column c2; --echo # --echo # Switching to connection 'default'. connection default; set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish'; --send select table_name, table_type, auto_increment, table_comment from information_schema.tables where table_schema='test' and table_name='t1'; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that upgrade from SNRW to X is blocked by presence of S lock. lock table t1 write; --echo # Sending: --send alter table t1 add column c2 int; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above upgrade of SNRW to X in ALTER TABLE is blocked --echo # because of S lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column c2 int"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping SELECT ... FROM I_S. --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --reap --echo # Restore the original state of the things. alter table t1 drop column c2; unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # --echo # 3) Acquire SR lock on the table. --echo # --echo # begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that S, SH, SR, SW and SWLP locks are compatible with it. handler t1 open; handler t1 close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; insert into t1 values (1), (1); delete low_priority from t1 limit 1; --echo # Check that SU lock is compatible with it. To do this use ALTER TABLE --echo # which will fail when constructing .frm and thus obtaining SU metadata --echo # lock. --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # Check that SRO lock is compatible with SR lock. lock table t1 read; select count(*) from t1; unlock tables; --echo # Check that SNW lock is compatible with it. To do this use ALTER TABLE --echo # which will fail during copying the table and thus obtaining SNW metadata --echo # lock. --error ER_DUP_ENTRY alter table t1 add primary key (c1); --echo # Check that SNRW lock is not compatible with SR lock. --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above LOCK TABLES is blocked because of SR lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Unblock LOCK TABLES. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLES. --reap delete from t1 limit 1; unlock tables; --echo # --echo # Switching to connection 'default'. connection default; begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that X lock is incompatible with SR lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above RENAME is blocked because of SR lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME TABLE. --reap --echo # Restore the original state of the things. rename table t2 to t1; --echo # --echo # Switching to connection 'default'. connection default; begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that upgrade from SNW to X is blocked by presence of SR lock. --echo # Sending: --send alter table t1 add column c2 int; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above ALTER TABLE is blocked because of SR lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column c2 int"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Unblock ALTER TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --reap --echo # Restore the original state of the things. alter table t1 drop column c2; --echo # --echo # There is no need to check that upgrade from SNRW to X is blocked --echo # by presence of SR lock because SNRW is incompatible with SR anyway. --echo # --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # --echo # 4) Acquire SW lock on the table. --echo # --echo # begin; insert into t1 values (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that S, SH, SR, SW and SWLP locks are compatible with it. handler t1 open; handler t1 close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; --echo # Disable result log to make test robust against --echo # effects of concurrent insert. --disable_result_log select * from t1; --enable_result_log insert into t1 values (1); delete low_priority from t1 limit 1; --echo # Check that SU lock is compatible with it. To do this use ALTER TABLE --echo # which will fail when constructing .frm and thus obtaining SU metadata --echo # lock. --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # Check that SRO lock is not compatible with SW lock; --echo # Sending: --send lock table t1 read; --echo # Switching to connection 'default'. connection default; --echo # Check that the above LOCK TABLE READ is blocked because of SW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 read"; --source include/wait_condition.inc --echo # Unblock LOCK TABLE READ. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLE READ. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; begin; insert into t1 values (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SNW lock is not compatible with SW lock. --echo # Again we use ALTER TABLE which fails during copying --echo # the table to avoid upgrade of SNW -> X. --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above ALTER TABLE is blocked because of SW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'default'. connection default; begin; insert into t1 values (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SNRW lock is not compatible with SW lock. --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above LOCK TABLES is blocked because of SW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Unblock LOCK TABLES. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLES. --reap delete from t1 limit 2; unlock tables; --echo # --echo # Switching to connection 'default'. connection default; begin; insert into t1 values (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that X lock is incompatible with SW lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above RENAME is blocked because of SW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME TABLE. --reap --echo # Restore the original state of the things. rename table t2 to t1; --echo # --echo # There is no need to check that upgrade from SNW/SNRW to X is --echo # blocked by presence of SW lock because SNW/SNRW is incompatible --echo # with SW anyway. --echo # --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # --echo # 5) Acquire SWLP lock on the table. --echo # --echo # begin; insert low_priority into t1 values (1), (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that S, SH, SR, SW and SWLP locks are compatible with it. handler t1 open; handler t1 close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; --echo # Disable result log to make test robust against --echo # effects of concurrent insert. --disable_result_log select * from t1; --enable_result_log delete from t1 limit 1; delete low_priority from t1 limit 1; --echo # Check that SU lock is compatible with it. To do this use ALTER TABLE --echo # which will fail when constructing .frm and thus obtaining SU metadata --echo # lock. --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # Check that SRO lock is not compatible with SWLP lock; --echo # Sending: --send lock table t1 read; --echo # Switching to connection 'default'. connection default; --echo # Check that the above LOCK TABLE READ is blocked because of SWLP lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 read"; --source include/wait_condition.inc --echo # Unblock LOCK TABLE READ. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLE READ. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; begin; insert low_priority into t1 values (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SNW lock is not compatible with SWLP lock. --echo # Again we use ALTER TABLE which fails during copying --echo # the table to avoid upgrade of SNW -> X. --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above ALTER TABLE is blocked because of SWLP lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'default'. connection default; begin; delete low_priority from t1 limit 2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SNRW lock is not compatible with SWLP lock. --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above LOCK TABLES is blocked because of SWLP lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Unblock LOCK TABLES. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLES. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; begin; insert low_priority into t1 values (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that X lock is incompatible with SWLP lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above RENAME is blocked because of SW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME TABLE. --reap --echo # Restore the original state of the things. rename table t2 to t1; --echo # --echo # There is no need to check that upgrade from SNW/SNRW to X is --echo # blocked by presence of SWLP lock because SNW/SNRW is incompatible --echo # with SWLP anyway. --echo # --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # --echo # 6) Acquire SU lock on the table. We have to use DEBUG_SYNC for --echo # this, to prevent SU from being immediately upgraded to X. --echo # set debug_sync= 'alter_opened_table SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that S, SH, SR, SW and SWLP locks are compatible with it. handler t1 open; handler t1 close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; insert into t1 values (1); delete low_priority from t1 limit 2; --echo # Check that SU lock is incompatible with SU lock. --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above ALTER is blocked because of SU lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # Unblock ALTERs. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping first ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping another ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'default'. connection default; set debug_sync= 'alter_opened_table SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that SRO lock is compatible with SU lock. lock tables t1 read; unlock tables; --echo # Check that SNRW lock is incompatible with SU lock. --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above LOCK TABLES is blocked because of SU lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Unblock ALTER and thus LOCK TABLES. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLES --reap insert into t1 values (1); unlock tables; --echo # --echo # Switching to connection 'default'. connection default; set debug_sync= 'alter_opened_table SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that X lock is incompatible with SU lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above RENAME is blocked because of SU lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Unblock ALTER and thus RENAME TABLE. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Now we have ALTER TABLE with SU->SNW and RENAME TABLE with pending --echo # X-lock. In this case ALTER TABLE should be chosen as victim. --echo # Reaping ALTER TABLE. --error ER_LOCK_DEADLOCK --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME TABLE --reap --echo # Revert back to original state of things. rename table t2 to t1; --echo # --echo # There is no need to check that upgrade from SNW/SNRW to X is --echo # blocked by presence of another SU lock because SNW/SNRW is --echo # incompatible with SU anyway. --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # --echo # 7) Acquire SRO lock on the table. --echo # --echo # lock table t1 read; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that S, SH and SR locks are compatible with it. handler t1 open; handler t1 close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; --echo # Check that SW lock is incompatible with SRO lock. --echo # Sending: --send delete from t1 limit 2; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above DELETE is blocked because of SRO lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete from t1 limit 2"; --source include/wait_condition.inc --echo # Unblock DELETE. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE. --reap --echo # --echo # Switching to connection 'default'. connection default; lock table t1 read; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SWLP lock is incompatible with SRO lock. --echo # Sending: --send insert low_priority into t1 values (1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above INSERT is blocked because of SRO lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert low_priority into t1 values (1)"; --source include/wait_condition.inc --echo # Unblock INSERT. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping INSERT. --reap --echo # --echo # Switching to connection 'default'. connection default; lock table t1 read; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SU lock is compatible with SRO lock. --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # Check that SRO lock is compatible with SRO lock. lock table t1 read; unlock tables; --echo # Check that SNW lock is compatible with SRO lock. --echo # Again we use ALTER TABLE which fails during copying --echo # the table to avoid upgrade of SNW -> X. --error ER_DUP_ENTRY alter table t1 add primary key (c1); --echo # Check that SNRW lock is incompatible with SRO lock. --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above LOCK TABLES is blocked because of SRO lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Unblock waiting LOCK TABLES. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLES --reap insert into t1 values (1); unlock tables; --echo # --echo # Switching to connection 'default'. connection default; lock table t1 read; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that X lock is incompatible with SRO lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above RENAME is blocked because of SRO lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME TABLE --reap --echo # Revert back to original state of things. rename table t2 to t1; --echo # --echo # Switching to connection 'default'. connection default; lock table t1 read; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that upgrade from SNW to X is blocked by presence of SRO lock. --echo # Sending: --send alter table t1 add column c2 int; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above ALTER TABLE is blocked because of SRO lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column c2 int"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Unblock ALTER TABLE. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --reap --echo # Restore the original state of the things. alter table t1 drop column c2; --echo # --echo # There is no need to check that upgrade from SNRW to X is --echo # blocked by presence of SRO lock because SNRW is incompatible --echo # with SRO anyway. --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # --echo # 8) Acquire SNW lock on the table. We have to use DEBUG_SYNC for --echo # this, to prevent SNW from being immediately upgraded to X. --echo # set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t1 add primary key (c1), lock=shared, algorithm=copy; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that S, SH and SR locks are compatible with it. handler t1 open; handler t1 close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; --echo # Check that SW lock is incompatible with SNW lock. --echo # Sending: --send delete from t1 limit 1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above DELETE is blocked because of SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete from t1 limit 1"; --source include/wait_condition.inc --echo # Unblock ALTER and thus DELETE. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE. --reap --echo # --echo # Switching to connection 'default'. connection default; set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t1 add primary key (c1), lock=shared, algorithm=copy; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that SWLP lock is incompatible with SNW lock. --echo # Sending: --send delete low_priority from t1 limit 1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above DELETE is blocked because of SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete low_priority from t1 limit 1"; --source include/wait_condition.inc --echo # Unblock ALTER. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE. --reap --echo # --echo # Switching to connection 'default'. connection default; set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t1 add primary key (c1), lock=shared, algorithm=copy; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that SU lock is incompatible with SNW lock. --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above ALTER is blocked because of SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # Unblock ALTERs. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping first ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping another ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # Switching to connection 'default'. connection default; set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t1 add primary key (c1), lock=shared, algorithm=copy; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that SRO lock is compatible with SNW lock. lock tables t1 read; unlock tables; --echo # --echo # Note that we can't easily check SNW vs SNW locks since --echo # SNW is only used by ALTER TABLE after upgrading from SU --echo # and SU is also incompatible with SNW. --echo # --echo # Check that SNRW lock is incompatible with SNW lock. --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above LOCK TABLES is blocked because of SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Unblock ALTER and thus LOCK TABLES. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLES --reap insert into t1 values (1); unlock tables; --echo # --echo # Switching to connection 'default'. connection default; set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t1 add primary key (c1), algorithm=copy, lock=shared; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; set debug_sync= 'now WAIT_FOR locked'; --echo # Check that X lock is incompatible with SNW lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above RENAME is blocked because of SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Unblock ALTER and thus RENAME TABLE. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME TABLE --reap --echo # Revert back to original state of things. rename table t2 to t1; --echo # --echo # There is no need to check that upgrade from SNW/SNRW to X is --echo # blocked by presence of another SNW lock because SNW/SNRW is --echo # incompatible with SNW anyway. --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # --echo # 9) Acquire SNRW lock on the table. --echo # --echo # lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that S and SH locks are compatible with it. handler t1 open; handler t1 close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; --echo # Check that SR lock is incompatible with SNRW lock. --echo # Sending: --send select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above SELECT is blocked because of SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "select count(*) from t1"; --source include/wait_condition.inc --echo # Unblock SELECT. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping SELECT. --reap --echo # --echo # Switching to connection 'default'. connection default; lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SW lock is incompatible with SNRW lock. --echo # Sending: --send delete from t1 limit 2; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above DELETE is blocked because of SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete from t1 limit 2"; --source include/wait_condition.inc --echo # Unblock DELETE. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE. --reap --echo # --echo # Switching to connection 'default'. connection default; lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SWLP lock is incompatible with SNRW lock. --echo # Sending: --send insert low_priority into t1 values (1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above INSERT is blocked because of SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert low_priority into t1 values (1)"; --source include/wait_condition.inc --echo # Unblock INSERT. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping INSERT. --reap --echo # --echo # Switching to connection 'default'. connection default; lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SU lock is incompatible with SNRW lock. --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above ALTER is blocked because of SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # Unblock ALTER. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'default'. connection default; lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SRO lock is incompatible with SNRW lock. --echo # Sending: --send lock table t1 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above LOCK TABLE READ is blocked because of SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 read"; --source include/wait_condition.inc --echo # Unblock LOCK TABLE READ. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLE READ. --reap unlock tables; --echo # --echo # Note that we can't easily check SNW vs SNRW locks since --echo # SNW is only used by ALTER TABLE after upgrading from SU --echo # and SU is also incompatible with SNRW. --echo # --echo # Switching to connection 'default'. connection default; lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that SNRW lock is incompatible with SNRW lock. --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above LOCK TABLES is blocked because of SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Unblock waiting LOCK TABLES. unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLES --reap insert into t1 values (1); unlock tables; --echo # --echo # Switching to connection 'default'. connection default; lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that X lock is incompatible with SNRW lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'default'. connection default; --echo # Check that the above RENAME is blocked because of SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME TABLE --reap --echo # Revert back to original state of things. rename table t2 to t1; --echo # --echo # There is no need to check that upgrade from SNW/SNRW to X is --echo # blocked by presence of another SNRW lock because SNW/SNRW is --echo # incompatible with SNRW anyway. --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # --echo # 10) Now do the same round of tests for X lock. We use additional --echo # table to get long-lived lock of this type. --echo # create table t2 (c1 int); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Take a lock on t2, so RENAME TABLE t1 TO t2 will get blocked --echo # after acquiring X lock on t1. lock tables t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME has acquired X lock on t1 and is waiting for t2. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that S lock in incompatible with X lock. --echo # Sending: --send handler t1 open; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above HANDLER statement is blocked because of X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "handler t1 open"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping HANDLER. --reap handler t1 close; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Prepare for blocking RENAME TABLE. lock tables t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME has acquired X lock on t1 and is waiting for t2. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SH lock in incompatible with X lock. --echo # Sending: --send select column_name from information_schema.columns where table_schema='test' and table_name='t1'; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above SELECT ... FROM I_S ... statement is blocked --echo # because of X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info like "select column_name from information_schema.columns%"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping SELECT ... FROM I_S. --reap --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Prepare for blocking RENAME TABLE. lock tables t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME has acquired X lock on t1 and is waiting for t2. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SR lock in incompatible with X lock. --echo # Sending: --send select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above SELECT statement is blocked --echo # because of X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "select count(*) from t1"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping SELECT. --reap --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Prepare for blocking RENAME TABLE. lock tables t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME has acquired X lock on t1 and is waiting for t2. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SW lock in incompatible with X lock. --echo # Sending: --send delete from t1 limit 2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above DELETE statement is blocked --echo # because of X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete from t1 limit 2"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE. --reap --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Prepare for blocking RENAME TABLE. lock tables t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME has acquired X lock on t1 and is waiting for t2. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SWLP lock in incompatible with X lock. --echo # Sending: --send insert low_priority into t1 values (1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above INSERT statement is blocked --echo # because of X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert low_priority into t1 values (1)"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping INSERT. --reap --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Prepare for blocking RENAME TABLE. lock tables t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME has acquired X lock on t1 and is waiting for t2. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SU lock is incompatible with X lock. --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above ALTER statement is blocked --echo # because of X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Prepare for blocking RENAME TABLE. lock tables t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME has acquired X lock on t1 and is waiting for t2. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SRO lock is incompatible with X lock. --echo # Sending: --send lock table t1 read; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above LOCK TABLE READ statement is blocked --echo # because of X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 read"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLE READ. --reap unlock tables; --echo # --echo # Note that we can't easily check SNW vs X locks since --echo # SNW is only used by ALTER TABLE after upgrading from SU --echo # and SU is also incompatible with X. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Prepare for blocking RENAME TABLE. lock tables t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME has acquired X lock on t1 and is waiting for t2. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SNRW lock is incompatible with X lock. --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above LOCK TABLE statement is blocked --echo # because of X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLE. --reap unlock tables; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Prepare for blocking RENAME TABLE. lock tables t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME has acquired X lock on t1 and is waiting for t2. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that X lock is incompatible with X lock. --echo # Sending: --send rename table t1 to t3; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above RENAME statement is blocked --echo # because of X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t3"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping RENAME. --reap rename table t3 to t1; --echo # --echo # B) Now let us test compatibility in cases when both locks --echo # are pending. I.e. let us test rules for priorities between --echo # different types of metadata locks. --echo # --echo # Note: No tests for pending SU lock as this lock requires --echo # even stronger active or pending lock. --echo # --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # --echo # 1) Check compatibility for pending SW lock. --echo # --echo # Acquire SRO lock in order to create pending SW lock later. lock table t1 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending SW lock. --echo # Sending: --send insert into t1 values (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that INSERT is waiting with pending SW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert into t1 values (1)"; --source include/wait_condition.inc --echo # Check that S, SH, SR locks are compatible with pending SW handler t1 open t; handler t close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; --echo # Can't check if SW and SWLP are compatible with pending SW --echo # as they are not compatible with active SRO. --echo # --echo # Check that SU lock is compatible with pending SW lock --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # Check that SRO lock is not compatible with pending SW lock --echo # Sending: --send lock table t1 read; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that LOCK TABLE is waiting due to pending SW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 read"; --source include/wait_condition.inc unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping INSERT --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping 2nd LOCK TABLE READ --reap unlock tables; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # --echo # Acquire SRO lock in order to create pending SW lock later. lock table t1 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending SW lock. --echo # Sending: --send delete from t1 limit 2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that DELETE is waiting with pending SW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete from t1 limit 2"; --source include/wait_condition.inc --echo # Check that SNW lock is compatible with pending SW lock --error ER_DUP_ENTRY alter table t1 add primary key (c1); --echo # --echo # We can't do similar check for SNRW and X locks because --echo # they will also be blocked by active SRO lock. --echo # --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping DELETE. --reap --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # --echo # 2) Check compatibility for pending SWLP lock. --echo # --echo # Acquire SRO lock in order to create pending SWLP lock later. lock table t1 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending SWLP lock. --echo # Sending: --send insert low_priority into t1 values (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that INSERT is waiting with pending SWLP lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert low_priority into t1 values (1)"; --source include/wait_condition.inc --echo # Check that S, SH, SR locks are compatible with pending SWLP handler t1 open t; handler t close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; --echo # Can't check if SW and SWLP are compatible with pending SWLP --echo # as they are not compatible with active SRO. --echo # --echo # Check that SU lock is compatible with pending SWLP lock --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # Check that SRO lock is compatible with pending SWLP lock lock table t1 read; unlock tables; --echo # Check that SNW lock is compatible with pending SWLP lock --error ER_DUP_ENTRY alter table t1 add primary key (c1); --echo # --echo # We can't do similar check for SNRW and X locks because --echo # they will also be blocked by active SRO lock. --echo # --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping INSERT. --reap --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # --echo # 3) Check compatibility for pending SRO lock. --echo # --echo # Acquire SW lock in order to create pending SRO lock later. begin; insert into t1 values (1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending SRO lock. --echo # Sending: --send lock table t1 read; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that LOCK TABLE READ is waiting with pending SRO lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 read"; --source include/wait_condition.inc --echo # Check that S, SH, SR, SW locks are compatible with pending SRO handler t1 open t; handler t close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; delete from t1 limit 1; --echo # Check that SWLP is incompatible with pending SRO --echo # Sending: --send delete low_priority from t1 limit 1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that DELETE is waiting with pending SRO lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete low_priority from t1 limit 1"; --source include/wait_condition.inc --echo # Unblock LOCK TABLE READ commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping LOCK TABLE READ --reap unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE --reap --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; insert into t1 values (1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending SRO lock. --echo # Sending: --send lock table t1 read; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that LOCK TABLE READ is waiting with pending SRO lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 read"; --source include/wait_condition.inc --echo # Check that SU lock is compatible with pending SRO lock --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # --echo # We can't do similar check for SRO, SNW, SNRW and X locks because --echo # they will also be blocked by active SW lock. --echo # --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Unblock LOCK TABLE READ. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping LOCK TABLE READ. --reap unlock tables; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # --echo # 4) Check compatibility for pending SNW lock. --echo # --echo # Acquire SW lock in order to create pending SNW lock later. begin; insert into t1 values (1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending SNW lock. --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that ALTER TABLE is waiting with pending SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # Check that S, SH and SR locks are compatible with pending SNW handler t1 open t; handler t close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; select count(*) from t1; --echo # Check that SW is incompatible with pending SNW --echo # Sending: --send delete from t1 limit 1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above DELETE is blocked because of pending SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete from t1 limit 1"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping ALTER. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE. --reap --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Acquire SW lock in order to create pending SNW lock later. begin; insert into t1 values (1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending SNW lock. --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that ALTER TABLE is waiting with pending SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # Check that SWLP is incompatible with pending SNW --echo # Sending: --send delete low_priority from t1 limit 1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above DELETE is blocked because of pending SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete low_priority from t1 limit 1"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping ALTER. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE. --reap --echo # --echo # We can't do similar check for SU as ALTER first acquire SU --echo # before upgrade to SNW. --echo # We can't do similar check for SRO, SNW, SNRW and X locks because --echo # they will also be blocked by active SW lock. --echo # --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # --echo # 5) Check compatibility for pending SNRW lock. --echo # --echo # Acquire SR lock in order to create pending SNRW lock. begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending SNRW lock. --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that LOCK TABLE is waiting with pending SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Check that S and SH locks are compatible with pending SNRW handler t1 open t; handler t close; select column_name from information_schema.columns where table_schema='test' and table_name='t1'; --echo # Check that SR is incompatible with pending SNRW --echo # Sending: --send select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above SELECT is blocked because of pending SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "select count(*) from t1"; --source include/wait_condition.inc --echo # Unblock LOCK TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping LOCK TABLE. --reap unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping SELECT. --reap --echo # Restore pending SNRW lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that LOCK TABLE is waiting with pending SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Check that SW is incompatible with pending SNRW --echo # Sending: --send insert into t1 values (1),(1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above INSERT is blocked because of pending SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert into t1 values (1),(1)"; --source include/wait_condition.inc --echo # Unblock LOCK TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping LOCK TABLE. --reap unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping INSERT. --reap --echo # Restore pending SNRW lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that LOCK TABLE is waiting with pending SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Check that SWLP is incompatible with pending SNRW --echo # Sending: --send delete low_priority from t1 limit 1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above DELETE is blocked because of pending SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete low_priority from t1 limit 1"; --source include/wait_condition.inc --echo # Unblock LOCK TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping LOCK TABLE. --reap unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE. --reap --echo # Restore pending SNRW lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that LOCK TABLE is waiting with pending SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Check that SU lock is compatible with pending SNRW lock --error ER_KEY_COLUMN_DOES_NOT_EXITS alter table t1 add index (not_exist); --echo # Check that SRO is incompatible with pending SNRW --echo # Sending: --send lock table t1 read; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above LOCK TABLE READ is blocked because --echo # of pending SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 read"; --source include/wait_condition.inc --echo # Unblock LOCK TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping LOCK TABLE. --reap unlock tables; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLE READ. --reap unlock tables; --echo # Restore pending SNRW lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that LOCK TABLE is waiting with pending SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Check that SNW is compatible with pending SNRW --echo # So ALTER TABLE statements are not starved by LOCK TABLEs. --error ER_DUP_ENTRY alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Unblock LOCK TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping LOCK TABLE. --reap unlock tables; --echo # --echo # We can't do similar check for SNRW and X locks because --echo # they will also be blocked by active SR lock. --echo # --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # --echo # 6) Check compatibility for pending X lock. --echo # --echo # Acquire SR lock in order to create pending X lock. begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending X lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME TABLE is waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SH locks are compatible with pending X select column_name from information_schema.columns where table_schema='test' and table_name='t1'; --echo # Check that S is incompatible with pending X --echo # Sending: --send handler t1 open; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above HANDLER OPEN is blocked because of pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "handler t1 open"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping HANDLER t1 OPEN. --reap handler t1 close; --echo # Restore pending X lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending X lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME TABLE is waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SR is incompatible with pending X --echo # Sending: --send select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above SELECT is blocked because of pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "select count(*) from t1"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping SELECT. --reap --echo # Restore pending X lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending X lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME TABLE is waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SW is incompatible with pending X --echo # Sending: --send delete from t1 limit 2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above DELETE is blocked because of pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete from t1 limit 2"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping DELETE. --reap --echo # Restore pending X lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending X lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME TABLE is waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SWLP is incompatible with pending X --echo # Sending: --send insert low_priority into t1 values (1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above INSERT is blocked because of pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert low_priority into t1 values (1)"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping INSERT. --reap --echo # Restore pending X lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending X lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME TABLE is waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SU is incompatible with pending X --echo # Sending: --send alter table t1 add index (not_exist); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above ALTER TABLE is blocked --echo # because of pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add index (not_exist)"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --error ER_KEY_COLUMN_DOES_NOT_EXITS --reap --echo # Restore pending X lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending X lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME TABLE is waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SRO is incompatible with pending X --echo # Sending: --send lock table t1 read; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above LOCK TABLE READ is blocked --echo # because of pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 read"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLE READ. --reap unlock tables; --echo # Restore pending X lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; begin; select count(*) from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending X lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME TABLE is waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SNW is incompatible with pending X --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above ALTER TABLE is blocked because of pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # Restore pending X lock. --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; handler t1 open; --echo # --echo # Switching to connection 'default'. connection default; --echo # Add pending X lock. --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that RENAME TABLE is waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that SNRW is incompatible with pending X --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'mdl_con3'. connection mdl_con3; --echo # Check that the above LOCK TABLES is blocked because of pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Unblock RENAME TABLE. handler t1 close; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reaping LOCK TABLES. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # --echo # C) Now let us test how type-of-operation locks are handled in --echo # transactional context. Obviously we are mostly interested --echo # in conflicting types of locks. --echo # --echo # Note: No tests for active/pending SU lock since --echo # ALTER TABLE is in its own transaction. --echo # No tests for active/pending SRO lock since --echo # it is pretty similar to SNW lock in this --echo # respect. --echo # --echo # --echo # 1) Let us check how various locks used within transactional --echo # context interact with active/pending SNW lock. --echo # --echo # We start with case when we are acquiring lock on the table --echo # which was not used in the transaction before. begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Create an active SNW lock on t2. --echo # We have to use DEBUG_SYNC facility as otherwise SNW lock --echo # will be immediately released (or upgraded to X lock). insert into t2 values (1), (1); set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t2 add primary key (c1), algorithm=copy, lock=shared; --echo # --echo # Switching to connection 'default'. connection default; set debug_sync= 'now WAIT_FOR locked'; --echo # SR lock should be acquired without any waiting. select count(*) from t2; commit; --echo # Now let us check that we will wait in case of SW lock. begin; select count(*) from t1; --echo # Sending: --send insert into t2 values (1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above INSERT is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert into t2 values (1)"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE and thus INSERT. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap INSERT. --reap commit; --echo # --echo # Now let us see what happens when we are acquiring lock on the table --echo # which is already used in transaction. --echo # --echo # *) First, case when transaction which has SR lock on the table also --echo # locked in SNW mode acquires yet another SR lock and then tries --echo # to acquire SW lock. begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Create an active SNW lock on t1. set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send alter table t1 add primary key (c1), algorithm=copy, lock=shared; --echo # --echo # Switching to connection 'default'. connection default; set debug_sync= 'now WAIT_FOR locked'; --echo # We should still be able to get SR lock without waiting. select count(*) from t1; --echo # Since the above ALTER TABLE is not upgrading SNW lock to X by waiting --echo # for SW lock we won't create deadlock. --echo # So the below INSERT should not end-up with ER_LOCK_DEADLOCK error. --echo # Sending: --send insert into t1 values (1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above INSERT is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert into t1 values (1)"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE and thus INSERT. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap INSERT. --reap commit; --echo # --echo # **) Now test in which transaction that has SW lock on the table --echo # against which there is pending SNW lock acquires SR and SW --echo # locks on this table. --echo # begin; insert into t1 values (1); --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Create pending SNW lock on t1. --echo # Sending: --send alter table t1 add primary key (c1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until ALTER TABLE starts waiting for SNW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add primary key (c1)"; --source include/wait_condition.inc --echo # We should still be able to get both SW and SR locks without waiting. select count(*) from t1; delete from t1 limit 1; --echo # Unblock ALTER TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap ALTER TABLE. --error ER_DUP_ENTRY --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # 2) Now similar tests for active SNW lock which is being upgraded --echo # to X lock. --echo # --echo # Again we start with case when we are acquiring lock on the --echo # table which was not used in the transaction before. begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Start transaction which will prevent SNW -> X upgrade from --echo # completing immediately. begin; select count(*) from t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Create SNW lock pending upgrade to X on t2. --echo # Sending: --send alter table t2 add column c2 int; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until ALTER TABLE starts waiting X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t2 add column c2 int"; --source include/wait_condition.inc --echo # Check that attempt to acquire SR lock on t2 causes waiting. --echo # Sending: --send select count(*) from t2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above SELECT is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "select count(*) from t2"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap ALTER TABLE. --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap SELECT. --reap commit; --echo # Do similar check for SW lock. begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Start transaction which will prevent SNW -> X upgrade from --echo # completing immediately. begin; select count(*) from t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Create SNW lock pending upgrade to X on t2. --echo # Sending: --send alter table t2 drop column c2; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until ALTER TABLE starts waiting X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t2 drop column c2"; --source include/wait_condition.inc --echo # Check that attempt to acquire SW lock on t2 causes waiting. --echo # Sending: --send insert into t2 values (1); --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above INSERT is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert into t2 values (1)"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap ALTER TABLE. --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap INSERT. --reap commit; --echo # --echo # Test for the case in which we are acquiring lock on the table --echo # which is already used in transaction. --echo # begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Create SNW lock pending upgrade to X. --echo # Sending: --send alter table t1 add column c2 int; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until ALTER TABLE starts waiting X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column c2 int"; --source include/wait_condition.inc --echo # Check that transaction is still able to acquire SR lock. select count(*) from t1; --echo # Waiting trying to acquire SW lock will cause deadlock and --echo # therefore should cause an error. --error ER_LOCK_DEADLOCK delete from t1 limit 1; --echo # Unblock ALTER TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap ALTER TABLE. --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # 3) Check how various locks used within transactional context --echo # interact with active/pending SNRW lock. --echo # --echo # Once again we start with case when we are acquiring lock on --echo # the table which was not used in the transaction before. begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; lock table t2 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # Attempt to acquire SR should be blocked. It should --echo # not cause errors as it does not creates deadlock. --echo # Sending: --send select count(*) from t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that the above SELECT is blocked let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "select count(*) from t2"; --source include/wait_condition.inc --echo # Unblock SELECT. unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap SELECT. --reap commit; --echo # Repeat the same test for SW lock. begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; lock table t2 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # Again attempt to acquire SW should be blocked and should --echo # not cause any errors. --echo # Sending: --send delete from t2 limit 1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Check that the above DELETE is blocked let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete from t2 limit 1"; --source include/wait_condition.inc --echo # Unblock DELETE. unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap DELETE. --reap commit; --echo # --echo # Now coverage for the case in which we are acquiring lock on --echo # the table which is already used in transaction and against --echo # which there is a pending SNRW lock request. --echo # --echo # *) Let us start with case when transaction has only a SR lock. --echo # begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until LOCK TABLE is blocked creating pending request for X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Check that another instance of SR lock is granted without waiting. select count(*) from t1; --echo # Attempt to wait for SW lock will lead to deadlock, thus --echo # the below statement should end with ER_LOCK_DEADLOCK error. --error ER_LOCK_DEADLOCK delete from t1 limit 1; --echo # Unblock LOCK TABLES. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap LOCK TABLES. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # **) Now case when transaction has a SW lock. --echo # begin; delete from t1 limit 1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Sending: --send lock table t1 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until LOCK TABLE is blocked creating pending request for X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t1 write"; --source include/wait_condition.inc --echo # Check that both SR and SW locks are granted without waiting --echo # and errors. select count(*) from t1; insert into t1 values (1, 1); --echo # Unblock LOCK TABLES. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap LOCK TABLES. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # 4) Check how various locks used within transactional context --echo # interact with active/pending X lock. --echo # --echo # As usual we start with case when we are acquiring lock on --echo # the table which was not used in the transaction before. begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Start transaction which will prevent X lock from going away --echo # immediately. begin; select count(*) from t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Create pending X lock on t2. --echo # Sending: --send rename table t2 to t3; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until RENAME TABLE starts waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t2 to t3"; --source include/wait_condition.inc --echo # Check that attempt to acquire SR lock on t2 causes waiting. --echo # Sending: --send select count(*) from t2; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above SELECT is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "select count(*) from t2"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap RENAME TABLE. --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap SELECT. --error ER_NO_SUCH_TABLE --reap commit; rename table t3 to t2; --echo # The same test for SW lock. begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Start transaction which will prevent X lock from going away --echo # immediately. begin; select count(*) from t2; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Create pending X lock on t2. --echo # Sending: --send rename table t2 to t3; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until RENAME TABLE starts waiting with pending X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t2 to t3"; --source include/wait_condition.inc --echo # Check that attempt to acquire SW lock on t2 causes waiting. --echo # Sending: --send delete from t2 limit 1; --echo # --echo # Switching to connection 'mdl_con2'. connection mdl_con2; --echo # Check that the above DELETE is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "delete from t2 limit 1"; --source include/wait_condition.inc --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap RENAME TABLE. --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap DELETE. --error ER_NO_SUCH_TABLE --reap commit; rename table t3 to t2; --echo # --echo # Coverage for the case in which we are acquiring lock on --echo # the table which is already used in transaction and against --echo # which there is a pending X lock request. --echo # --echo # *) The first case is when transaction has only a SR lock. --echo # begin; select count(*) from t1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until RENAME TABLE is blocked creating pending request for X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that another instance of SR lock is granted without waiting. select count(*) from t1; --echo # Attempt to wait for SW lock will lead to deadlock, thus --echo # the below statement should end with ER_LOCK_DEADLOCK error. --error ER_LOCK_DEADLOCK delete from t1 limit 1; --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # **) The second case is when transaction has a SW lock. --echo # begin; delete from t1 limit 1; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Sending: --send rename table t1 to t2; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until RENAME TABLE is blocked creating pending request for X lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t2"; --source include/wait_condition.inc --echo # Check that both SR and SW locks are granted without waiting --echo # and errors. select count(*) from t1; insert into t1 values (1, 1); --echo # Unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'mdl_con1'. connection mdl_con1; --echo # Reap RENAME TABLE. --error ER_TABLE_EXISTS_ERROR --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # Clean-up. disconnect mdl_con1; disconnect mdl_con2; disconnect mdl_con3; set debug_sync= 'RESET'; drop table t1, t2; --echo # --echo # Additional coverage for some scenarios in which use of S and SR --echo # metadata locks by HANDLER statement might have caused deadlocks. --echo # --disable_warnings drop table if exists t1, t2; --enable_warnings connect(handler_con1,localhost,root,,); connect(handler_con2,localhost,root,,); connection default; create table t1 (i int); create table t2 (j int); insert into t1 values (1); --echo # --echo # First, check scenario in which we upgrade SNRW lock to X lock --echo # on a table while having HANDLER READ trying to acquire SR --echo # on the same table. --echo # handler t1 open; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; lock table t1 write; --echo # Upgrade SNRW to X lock. --echo # Sending: --send alter table t1 add column j int; --echo # --echo # Switching to connection 'handler_con2'. connection handler_con2; --echo # Wait until ALTER is blocked during upgrade. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column j int"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # The below statement should not cause deadlock. --send handler t1 read first; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Reap ALTER TABLE. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap HANDLER READ. --reap handler t1 close; --echo # --echo # Now, check scenario in which upgrade of SNRW lock to X lock --echo # can be blocked by HANDLER which is open in connection currently --echo # waiting to get SW lock owned by connection doing upgrade. --echo # handler t1 open; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; lock table t1 write, t2 read; --echo # --echo # Switching to connection 'default'. connection default; --echo # Execute statement which will be blocked on SRO lock --echo # owned by connection 'handler_con1'. --echo # Sending: --send insert into t2 values (1); --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Wait until INSERT is blocked due to SRO lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert into t2 values (1)"; --source include/wait_condition.inc --echo # Sending 'alter table t1 drop column j'. It should not cause --echo # deadlock. send alter table t1 drop column j; --echo # Switching to connection 'handler_con2'. connection handler_con2; --echo # Wait until ALTER is blocked during upgrade. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 drop column j"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap INSERT. --error ER_LOCK_DEADLOCK --reap handler t1 close; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Reaping 'alter table t1 drop column j' --reap unlock tables; --echo # Switching to connection 'default'. connection default; --echo # Then, check the scenario in which upgrade of SNRW lock to X --echo # lock is blocked by HANDLER which is open in connection currently --echo # waiting to get SW lock on the same table. --echo # handler t1 open; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; lock table t1 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # The below insert should be blocked because active SNRW lock on 't1'. --echo # Sending: --send insert into t1 values (1); --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Wait until INSERT is blocked because of SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert into t1 values (1)"; --source include/wait_condition.inc --echo # The below ALTER TABLE will be blocked because of presence of HANDLER. --echo # Sending: --send alter table t1 add column j int; --echo # --echo # Switching to connection 'default'. connection default; --echo # INSERT should be chosen as victim for resolving deadlock. --echo # Reaping INSERT. --error ER_LOCK_DEADLOCK --reap --echo # Close HANDLER to unblock ALTER TABLE. handler t1 close; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Reaping ALTER TABLE. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # Then, test in which upgrade of SNRW lock to X lock is blocked --echo # by HANDLER which is open in connection currently waiting to get --echo # SR lock on the table on which lock is upgraded. --echo # handler t1 open; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; lock table t1 write, t2 write; --echo # --echo # Switching to connection 'default'. connection default; --echo # The below insert should be blocked because active SNRW lock on 't1'. --echo # Sending: --send insert into t2 values (1); --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Wait until INSERT is blocked because of SNRW lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert into t2 values (1)"; --source include/wait_condition.inc --echo # The below ALTER TABLE will be blocked because of presence of HANDLER. --echo # Sending: --send alter table t1 drop column j; --echo # --echo # Switching to connection 'default'. connection default; --echo # INSERT should be chosen as victim for resolving deadlock. --echo # Reaping INSERT. --error ER_LOCK_DEADLOCK --reap --echo # Close HANDLER to unblock ALTER TABLE. handler t1 close; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Reaping ALTER TABLE. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # Finally, check scenario in which upgrade of SNRW lock to X lock --echo # can be blocked by HANDLER which is open in connection currently --echo # waiting to get thr_lock.c lock owned by connection doing upgrade. --echo # handler t1 open; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; lock table t1 write, t2 read local; --echo # --echo # Switching to connection 'default'. connection default; --echo # Execute statement which will be blocked on thr_lock.c lock --echo # owned by connection 'handler_con1'. --echo # Sending: --send update t2 set j=3; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Wait until UPDATE is blocked due to thr_lock.c lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table level lock" and info = "update t2 set j=3"; --source include/wait_condition.inc --echo # Sending 'alter table t1 add column j'. It should not cause --echo # deadlock. send alter table t1 add column j int; --echo # Switching to connection 'handler_con2'. connection handler_con2; --echo # Wait until ALTER is blocked during upgrade. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column j int"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap UPDATE. --error ER_LOCK_ABORTED --reap handler t1 close; --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Reaping 'alter table t1 drop column j' --reap unlock tables; --echo # --echo # Also cover situation when HANDLER READ is aborted while waiting on --echo # thr_lock.c lock in order to avoid deadlock due to another connection --echo # performing DDL on another table open by HANDLER in the first one. --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; handler t1 open; handler t2 open; --echo # --echo # Switching to connection 'default'. connection default; lock table t1 write, t2 read local; --echo # --echo # Switching to connection 'handler_con2'. connection handler_con2; --echo # Execute statement which will be blocked on thr_lock.c lock --echo # owned by connection 'default' and will block further attempts --echo # to read from 't2. --echo # Sending: --send update t2 set j=3; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until UPDATE is blocked due to thr_lock.c lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table level lock" and info = "update t2 set j=3"; --source include/wait_condition.inc --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Sending --send handler t2 read first; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until HANDLER READ is blocked due to pending thr_lock.c lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table level lock" and info = "handler t2 read first"; --source include/wait_condition.inc --echo # ALTER TABLE t1 should not block. HANDLER t2 READ should get aborted --echo # from its wait on thr_lock.c lock and 'handler_con1' should re-open --echo # tables opened by HANDLER statemets. alter table t1 drop column j; unlock tables; --echo # --echo # Switching to connection 'handler_con2'. connection handler_con2; --echo # Reap UPDATE --reap --echo # --echo # Switching to connection 'handler_con1'. connection handler_con1; --echo # Reap HANDLER READ --reap handler t1 close; handler t2 close; --echo # Switching to connection 'default'. connection default; --echo # Clean-up. disconnect handler_con1; disconnect handler_con2; drop tables t1, t2; --echo # --echo # Test coverage for basic deadlock detection in metadata --echo # locking subsystem. --echo # --disable_warnings drop tables if exists t0, t1, t2, t3, t4, t5; --enable_warnings set debug_sync= 'RESET'; connect(deadlock_con1,localhost,root,,); connect(deadlock_con2,localhost,root,,); connect(deadlock_con3,localhost,root,,); connection default; create table t1 (i int); create table t2 (j int); create table t3 (k int); create table t4 (k int); --echo # --echo # Test for the case in which no deadlock occurs. --echo # --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; begin; insert into t1 values (1); --echo # --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; begin; insert into t2 values (1); --echo # --echo # Switching to connection 'default'. connection default; --echo # Send: --send rename table t2 to t0, t3 to t2, t0 to t3; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Wait until the above RENAME TABLE is blocked because it has to wait --echo # for 'deadlock_con2' which holds shared metadata lock on 't2'. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t2 to t0, t3 to t2, t0 to t3"; --source include/wait_condition.inc --echo # The below statement should wait for exclusive metadata lock --echo # on 't2' to go away and should not produce ER_LOCK_DEADLOCK --echo # as no deadlock is possible in this situation. --echo # Send: --send select * from t2; --echo # --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Wait until the above SELECT * FROM t2 is starts waiting --echo # for an exclusive metadata lock to go away. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "select * from t2"; --source include/wait_condition.inc --echo # --echo # Unblock RENAME TABLE by releasing shared metadata lock on t2. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap RENAME TABLE. --reap --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Reap SELECT. --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # --echo # Let us check that in the process of waiting for conflicting lock --echo # on table 't2' to go away transaction in connection 'deadlock_con1' --echo # has not released metadata lock on table 't1'. --echo # Send: --send rename table t1 to t0, t3 to t1, t0 to t3; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Wait until the above RENAME TABLE is blocked because it has to wait --echo # for 'deadlock_con1' which should still hold shared metadata lock on --echo # table 't1'. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t0, t3 to t1, t0 to t3"; --source include/wait_condition.inc --echo # Commit transaction to unblock RENAME TABLE. commit; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap RENAME TABLE. --reap --echo # --echo # Test for case when deadlock occurs and should be detected immediately. --echo # --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; begin; insert into t2 values (2); --echo # --echo # Switching to connection 'default'. connection default; --echo # Send: --send rename table t2 to t0, t1 to t2, t0 to t1; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Wait until the above RENAME TABLE is blocked because it has to wait --echo # for 'deadlock_con1' which holds shared metadata lock on 't2'. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t2 to t0, t1 to t2, t0 to t1"; --source include/wait_condition.inc --echo # --echo # The below statement should not wait as doing so will cause deadlock. --echo # Instead it should fail and emit ER_LOCK_DEADLOCK statement and --echo # transaction should be rolled back. --error ER_LOCK_DEADLOCK select * from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap RENAME TABLE. --reap --echo # --echo # Test for the case in which deadlock also occurs but not immediately. --echo # --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; begin; insert into t2 values (1); --echo # --echo # Switching to connection 'default'. connection default; lock table t1 write; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # The below SELECT statement should wait for metadata lock --echo # on table 't1' and should not produce ER_LOCK_DEADLOCK --echo # immediately as no deadlock is possible at the moment. --send select * from t1; --echo # --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Wait until the above SELECT * FROM t1 is starts waiting --echo # for an UNRW metadata lock to go away. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "select * from t1"; --source include/wait_condition.inc --echo # Send RENAME TABLE statement that will deadlock with the --echo # SELECT statement and thus should abort the latter. --send rename table t1 to t0, t2 to t1, t0 to t2; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait till above RENAME TABLE is blocked while holding --echo # pending X lock on t1. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t0, t2 to t1, t0 to t2"; --source include/wait_condition.inc --echo # Allow the above RENAME TABLE to acquire lock on t1 and --echo # create pending lock on t2 thus creating deadlock. unlock tables; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Since the latest RENAME TABLE entered in deadlock with SELECT --echo # statement the latter should be aborted and emit ER_LOCK_DEADLOCK --echo # error and transaction should be rolled back. --echo # Reap SELECT * FROM t1. --error ER_LOCK_DEADLOCK --reap --echo # --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Reap RENAME TABLE ... . --reap; --echo # --echo # Switching to connection 'default'. connection default; drop tables t1, t2, t3, t4; --echo # --echo # Now, test case which shows that deadlock detection empiric --echo # also takes into account requests for metadata lock upgrade. --echo # create table t1 (i int); insert into t1 values (1); --echo # Avoid race which occurs when SELECT in 'deadlock_con1' connection --echo # accesses table before the above INSERT unlocks the table and thus --echo # its result becomes visible to other connections. select * from t1; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; begin; select * from t1; --echo # --echo # Switching to connection 'default'. connection default; --echo # Send: --send alter table t1 add column j int, rename to t2; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Wait until the above ALTER TABLE ... RENAME acquires exclusive --echo # metadata lock on 't2' and starts waiting for connection --echo # 'deadlock_con1' which holds shared lock on 't1'. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 add column j int, rename to t2"; --source include/wait_condition.inc --echo # The below statement should not wait as it will cause deadlock. --echo # An appropriate error should be reported instead and transaction --echo # should be rolled back. --error ER_LOCK_DEADLOCK select * from t2; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap ALTER TABLE ... RENAME. --reap drop table t2; --echo # --echo # Test that in situation when MDL subsystem detects a deadlock --echo # but it turns out that it can be resolved by backing-off locks --echo # acquired by one of participating transactions (which is --echo # possible when one of transactions consists only of currently --echo # executed statement, e.g. in autocommit mode) no error is --echo # reported. --echo # create table t1 (i int); create table t2 (j int); --echo # Ensure that the below SELECT stops once it has acquired metadata --echo # lock on table 't2'. set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish'; --echo # Sending: --send select * from t2, t1 --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Wait till SELECT acquires MDL on 't2' and starts waiting for signal. set debug_sync= 'now WAIT_FOR locked'; --echo # Sending: --send lock tables t1 write, t2 write --echo # --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Wait until LOCK TABLES acquires SNRW lock on 't1' and is blocked --echo # while trying to acquire SNRW lock on 't1'. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock tables t1 write, t2 write"; --source include/wait_condition.inc --echo # Resume SELECT execution, this should eventually unblock LOCK TABLES. set debug_sync= 'now SIGNAL finish'; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Reaping LOCK TABLES. --reap unlock tables; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping SELECT. It succeed and not report ER_LOCK_DEADLOCK error. --reap drop tables t1, t2; --echo # --echo # Test coverage for situation in which a race has happened --echo # during deadlock detection process which led to unwarranted --echo # ER_LOCK_DEADLOCK error. --echo # create table t1 (i int); --echo # Ensure that ALTER waits once it has acquired SNW lock. set debug_sync='alter_table_copy_after_lock_upgrade SIGNAL parked1 WAIT_FOR go1'; --echo # Sending: --send alter table t1 add column j int --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Wait till ALTER acquires SNW lock and stops. set debug_sync='now WAIT_FOR parked1'; --echo # Ensure that INSERT is paused once it detects that there is --echo # a conflicting metadata lock so it has to wait, but before --echo # deadlock detection is run. set debug_sync='mdl_acquire_lock_wait SIGNAL parked2 WAIT_FOR go2'; --echo # Sending: --send insert into t1 values () --echo # --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Wait till INSERT is paused. set debug_sync='now WAIT_FOR parked2'; --echo # Resume ALTER execution. Eventually it will release its --echo # metadata lock and INSERT's request for SW lock will be --echo # satisified. set debug_sync='now SIGNAL go1'; --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping ALTER TABLE. --reap --echo # Add a new request for SNW lock to waiting graph. --echo # Sending: --send alter table t1 drop column j --echo # --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Wait until ALTER is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "alter table t1 drop column j"; --source include/wait_condition.inc --echo # Resume INSERT so it can start deadlock detection. --echo # --echo # At this point there is a discrepancy between the fact that INSERT's --echo # SW lock is already satisfied, but INSERT's connection is still --echo # marked as waiting for it. Looking for a loop in waiters graph --echo # without additional checks has detected a deadlock (INSERT waits --echo # for SW lock; which is not granted because of pending SNW lock from --echo # ALTER; which waits for active SW lock from INSERT). Since requests --echo # for SW and SNW locks have same weight ALTER was selected as a victim --echo # and ended with ER_LOCK_DEADLOCK error. set debug_sync='now SIGNAL go2'; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Reaping INSERT. --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # Reaping ALTER. It should succeed and not produce ER_LOCK_DEADLOCK. --reap 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'; --echo # Switching to connection 'deadlock_con1'. 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) --echo # Switching to connection 'deadlock_con2'. 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; --echo # Switching to connection 'deadlock_con3'. 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'; --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Reap FLUSH TABLES WITH READ LOCK. reap; unlock tables; --echo # Switching to connection 'deadlock_con1'. 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'; --echo # Switching to connection 'deadlock_con2'. 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; --echo # Switching to connection 'deadlock_con1'. 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); --echo # Switching to connection 'deadlock_con3'. 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'; --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Reap FLUSH TABLES WITH READ LOCK. reap; unlock tables; --echo # Switching to connection 'deadlock_con1'. 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'; --echo # Switching to connection 'deadlock_con1'. 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; --echo # Switching to connection 'deadlock_con2'. 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; --echo # Switching to connection 'deadlock_con3'. 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; --echo # Switching to connection 'default'. 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'; --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Reap FLUSH TABLES WITH READ LOCK. reap; --echo # Unblock DROP TABLES. unlock tables; --echo # Switching to connection 'deadlock_con3'. connection deadlock_con3; --echo # Reap DROP TABLES. reap; --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Reap SELECT. It should emit error about missing table. --error ER_NO_SUCH_TABLE reap; --echo # Switching to connection 'default'. connection default; set debug_sync= 'RESET'; --echo # --echo # Test coverage for scenario when deadlock is caused by LOCK TABLES --echo # implicitly acquiring "strong" metadata lock in order that is --echo # different from one used by other DDL. --echo # --echo # Other DDL should not be chosen as a deadlock victim in this case. --echo # Instead LOCK TABLES should be chosen as a victim and deadlock --echo # should be handled by executing back-off and retry of lock --echo # acquisition, without reporting any error to user. create table t1(i int); create table t2(j int); create table t3(j int); create trigger t3_bi before insert on t3 for each row insert into t1 values (1); --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; begin; select * from t2; --echo # --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Send: --send rename table t1 to t0, t2 to t1, t3 to t2, t0 to t3 --echo # --echo # Switching to connection 'deadlock_con3'. connection deadlock_con3; --echo # Wait until the above RENAME TABLE is blocked because it has to wait --echo # for 'deadlock_con1' which holds SR lock on 't2'. At this point it --echo # should already acquire X lock on 't0' and 't1'. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "rename table t1 to t0, t2 to t1, t3 to t2, t0 to t3"; --source include/wait_condition.inc --echo # The below statement should acquire SNRW lock on 't3' and got --echo # blocked trying to acquire SNRW lock on 't1'. --echo # Sending: --send lock table t3 write; --echo # --echo # Switching to connection 'deadlock_con1'. connection deadlock_con1; --echo # Wait until the above LOCK TABLE WRITE starts waiting. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock table t3 write"; --source include/wait_condition.inc --echo # --echo # Unblock RENAME TABLE by releasing SR on t2. commit; --echo # --echo # Switching to connection 'deadlock_con2'. connection deadlock_con2; --echo # Reap RENAME TABLE. It should succeed. --reap --echo # --echo # Switching to connection 'deadlock_con3'. connection deadlock_con3; --echo # Reap LOCK TABLES WRITE. It should succeed too. --echo # New version of 't3' should be visible. --reap select * from t3; unlock table; --echo # --echo # Switching to connection 'default'. connection default; --echo # Clean-up. rename table t3 to t0, t2 to t3, t1 to t2, t0 to t1; drop trigger t3_bi; drop tables t1, t2, t3; disconnect deadlock_con1; disconnect deadlock_con2; disconnect deadlock_con3; --echo # --echo # Test for a scenario in which FLUSH TABLES WITH READ LOCK --echo # used to erroneously release metadata locks. --echo # connect(con1,localhost,root,,); connect(con2,localhost,root,,); connection default; --disable_warnings drop tables if exists t1, t2; --enable_warnings set debug_sync= 'RESET'; create table t1(i int); create table t2(j int); --echo # Switching to connection 'con2'. connection con2; set debug_sync='open_tables_after_open_and_process_table SIGNAL parked WAIT_FOR go'; --echo # The below FLUSH TABLES WITH READ LOCK should acquire --echo # SNW locks on t1 and t2, open table t1 and block on the debug --echo # sync point. --echo # Sending: send flush tables t1, t2 with read lock; --echo # Switching to connection 'con1'. connection con1; --echo # Wait till FLUSH TABLES WITH READ LOCK stops. set debug_sync='now WAIT_FOR parked'; --echo # Start a statement which will flush all tables and thus --echo # invalidate table t1 open by FLUSH TABLES WITH READ LOCK. --echo # Sending: send flush tables; --echo # Switching to connection 'default'. connection default; --echo # Wait till the above FLUSH TABLES blocks. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table flush" and info = "flush tables"; --source include/wait_condition.inc --echo # Resume FLUSH TABLES WITH READ LOCK, so it tries to open t2 --echo # discovers that its t1 is obsolete and tries to reopen all tables. --echo # Such reopen should not cause releasing of SNW metadata locks --echo # which would result in assertion failures. set debug_sync='now SIGNAL go'; --echo # Switching to connection 'con2'. connection con2; --echo # Reap FLUSH TABLES WITH READ LOCK. reap; unlock tables; --echo # Switching to connection 'con1'. connection con1; --echo # Reap FLUSH TABLES. reap; --echo # Clean-up. --echo # Switching to connection 'default'. connection default; drop tables t1, t2; set debug_sync= 'RESET'; disconnect con1; disconnect con2; --echo # --echo # Test for bug #46748 "Assertion in MDL_context::wait_for_locks() --echo # on INSERT + CREATE TRIGGER". --echo # --disable_warnings drop tables if exists t1, t2, t3, t4, t5; --enable_warnings --echo # Let us simulate scenario in which we open some tables from extended --echo # part of prelocking set but then encounter conflicting metadata lock, --echo # so have to back-off and wait for it to go away. connect (con1root,localhost,root,,test,,); connect (con2root,localhost,root,,test,,); connection default; create table t1 (i int); create table t2 (j int); create table t3 (k int); create table t4 (l int); create trigger t1_bi before insert on t1 for each row insert into t2 values (new.i); create trigger t2_bi before insert on t2 for each row insert into t3 values (new.j); --echo # --echo # Switching to connection 'con1root'. connection con1root; lock tables t4 read; --echo # --echo # Switching to connection 'con2root'. connection con2root; --echo # Send : --send rename table t3 to t5, t4 to t3; --echo # --echo # Switching to connection 'default'. connection default; --echo # Wait until the above RENAME TABLE adds pending requests for exclusive --echo # metadata lock on its tables and blocks due to 't4' being used by LOCK --echo # TABLES. let $wait_condition= select count(*)= 1 from information_schema.processlist where state= 'Waiting for table metadata lock' and info='rename table t3 to t5, t4 to t3'; --source include/wait_condition.inc --echo # Send : --send insert into t1 values (1); --echo # --echo # Switching to connection 'con1root'. connection con1root; --echo # Wait until INSERT statement waits due to encountering pending --echo # exclusive metadata lock on 't3'. let $wait_condition= select count(*)= 1 from information_schema.processlist where state= 'Waiting for table metadata lock' and info='insert into t1 values (1)'; --source include/wait_condition.inc unlock tables; --echo # --echo # Switching to connection 'con2root'. connection con2root; --echo # Reap RENAME TABLE. --reap --echo # --echo # Switching to connection 'default'. connection default; --echo # Reap INSERT. --reap --echo # Clean-up. disconnect con1root; disconnect con2root; drop tables t1, t2, t3, t5; --echo # --echo # Bug#42546 - Backup: RESTORE fails, thinking it finds an existing table --echo # --disable_warnings DROP TABLE IF EXISTS t1; --enable_warnings set @save_log_output=@@global.log_output; set global log_output=file; connect(con2, localhost, root,,); --echo # --echo # Test 1: CREATE TABLE --echo # --echo # Connection 2 connection con2; --echo # Start insert on the not-yet existing table --echo # Wait after taking the MDL lock SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish'; --send INSERT INTO t1 VALUES(1,"def") --echo # Connection 1 connection default; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Now INSERT has a MDL on the non-existent table t1. --echo # --echo # Continue the INSERT once CREATE waits for exclusive lock SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL finish'; --echo # Try to create that table. --send CREATE TABLE t1 (c1 INT, c2 VARCHAR(100), KEY(c1)) --echo # Connection 2 --echo # Insert fails connection con2; --error ER_NO_SUCH_TABLE --reap --echo # Connection 1 connection default; --reap; SET DEBUG_SYNC= 'RESET'; SHOW TABLES; --disable_warnings DROP TABLE IF EXISTS t1; --enable_warnings --echo # --echo # Test 2: CREATE TABLE LIKE --echo # CREATE TABLE t2 (c1 INT, c2 VARCHAR(100), KEY(c1)); --echo # Connection 2 connection con2; --echo # Start insert on the not-yet existing table --echo # Wait after taking the MDL SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish'; --send INSERT INTO t1 VALUES(1,"def") --echo # Connection 1 connection default; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Now INSERT has a MDL on the non-existent table t1. --echo # --echo # Continue the INSERT once CREATE waits for exclusive lock SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL finish'; --echo # Try to create that table. --send CREATE TABLE t1 LIKE t2 --echo # Connection 2 --echo # Insert fails connection con2; --error ER_NO_SUCH_TABLE --reap --echo # Connection 1 connection default; --reap SET DEBUG_SYNC= 'RESET'; SHOW TABLES; DROP TABLE t2; disconnect con2; --disable_warnings DROP TABLE IF EXISTS t1; --enable_warnings set global log_output=@save_log_output; --echo # --echo # Bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE HIGH_PRIORITY --echo # FOR UPDATE" --echo # --disable_warnings drop tables if exists t1, t2; --enable_warnings connect (con46044, localhost, root,,); connect (con46044_2, localhost, root,,); connection default; create table t1 (i int); insert into t1 values(1); --echo # Let us check that we won't deadlock if during filling --echo # of I_S table we encounter conflicting metadata lock --echo # which owner is in its turn waiting for our connection. lock tables t1 read; --echo # Switching to connection 'con46044_2'. connection con46044_2; --echo # Sending: --send lock tables t1 write; --echo # Switching to connection 'con46044'. connection con46044; --echo # Waiting until LOCK TABLES WRITE is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "lock tables t1 write"; --source include/wait_condition.inc --echo # Sending: --send create table t2 select * from t1; --echo # Switching to connection 'default'. connection default; --echo # Waiting until CREATE TABLE ... SELECT ... is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "create table t2 select * from t1"; --source include/wait_condition.inc --echo # First let us check that SHOW FIELDS/DESCRIBE doesn't --echo # gets blocked and emits and error. --error ER_WARN_I_S_SKIPPED_TABLE show fields from t2; --echo # Now test for I_S query which reads only .FRMs. --echo # --echo # Query below should only emit a warning. select column_name from information_schema.columns where table_schema='test' and table_name='t2'; --echo # Finally, test for I_S query which does full-blown table open. --echo # --echo # Query below should not be blocked. Warning message should be --echo # stored in the 'table_comment' column. select table_name, table_type, auto_increment, table_comment from information_schema.tables where table_schema='test' and table_name='t2'; --echo # Switching to connection 'default'. connection default; unlock tables; --echo # Switching to connection 'con46044_2'. connection con46044_2; --echo # Reaping LOCK TABLES WRITE --reap unlock tables; --echo # Switching to connection 'con46044'. connection con46044; --echo # Reaping CREATE TABLE ... SELECT ... . --reap drop table t2; --echo # --echo # Let us also check that queries to I_S wait for conflicting metadata --echo # locks to go away instead of skipping table with a warning in cases --echo # when deadlock is not possible. This is a nice thing from compatibility --echo # and ease of use points of view. --echo # --echo # We check same three queries to I_S in this new situation. --echo # Switching to connection 'con46044_2'. connection con46044_2; lock tables t1 write; --echo # Switching to connection 'con46044'. connection con46044; --echo # Sending: --send create table t2 select * from t1; --echo # Switching to connection 'default'. connection default; --echo # Waiting until CREATE TABLE ... SELECT ... is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "create table t2 select * from t1"; --source include/wait_condition.inc --echo # Let us check that SHOW FIELDS/DESCRIBE gets blocked. --echo # Sending: --send show fields from t2; --echo # Switching to connection 'con46044_2'. connection con46044_2; --echo # Wait until SHOW FIELDS gets blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "show fields from t2"; --source include/wait_condition.inc unlock tables; --echo # Switching to connection 'con46044'. connection con46044; --echo # Reaping CREATE TABLE ... SELECT ... . --reap --echo # Switching to connection 'default'. connection default; --echo # Reaping SHOW FIELDS ... --reap drop table t2; --echo # Switching to connection 'con46044_2'. connection con46044_2; lock tables t1 write; --echo # Switching to connection 'con46044'. connection con46044; --echo # Sending: --send create table t2 select * from t1; --echo # Switching to connection 'default'. connection default; --echo # Waiting until CREATE TABLE ... SELECT ... is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "create table t2 select * from t1"; --source include/wait_condition.inc --echo # Check that I_S query which reads only .FRMs gets blocked. --echo # Sending: --send select column_name from information_schema.columns where table_schema='test' and table_name='t2'; --echo # Switching to connection 'con46044_2'. connection con46044_2; --echo # Wait until SELECT COLUMN_NAME FROM I_S.COLUMNS gets blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info like "select column_name from information_schema.columns%"; --source include/wait_condition.inc unlock tables; --echo # Switching to connection 'con46044'. connection con46044; --echo # Reaping CREATE TABLE ... SELECT ... . --reap --echo # Switching to connection 'default'. connection default; --echo # Reaping SELECT COLUMN_NAME FROM I_S.COLUMNS --reap drop table t2; --echo # Switching to connection 'con46044_2'. connection con46044_2; lock tables t1 write; --echo # Switching to connection 'con46044'. connection con46044; --echo # Sending: --send create table t2 select * from t1; --echo # Switching to connection 'default'. connection default; --echo # Waiting until CREATE TABLE ... SELECT ... is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "create table t2 select * from t1"; --source include/wait_condition.inc --echo # Finally, check that I_S query which does full-blown table open --echo # also gets blocked. --echo # Sending: --send select table_name, table_type, auto_increment, table_comment from information_schema.tables where table_schema='test' and table_name='t2'; --echo # Switching to connection 'con46044_2'. connection con46044_2; --echo # Wait until SELECT ... FROM I_S.TABLES gets blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info like "select table_name, table_type, auto_increment, table_comment from information_schema.tables%"; --source include/wait_condition.inc unlock tables; --echo # Switching to connection 'con46044'. connection con46044; --echo # Reaping CREATE TABLE ... SELECT ... . --reap --echo # Switching to connection 'default'. connection default; --echo # Reaping SELECT ... FROM I_S.TABLES --reap drop table t2; --echo # Switching to connection 'default'. connection default; --echo # Clean-up. disconnect con46044; disconnect con46044_2; drop table t1; --echo # --echo # Test for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed --echo # in case of ALTER". --echo # --disable_warnings drop table if exists t1; --enable_warnings set debug_sync= 'RESET'; connect (con46273,localhost,root,,test,,); connection default; create table t1 (c1 int primary key, c2 int, c3 int); insert into t1 values (1,1,0),(2,2,0),(3,3,0),(4,4,0),(5,5,0); begin; select * from t1 where c2 = 3; --echo # --echo # Switching to connection 'con46273'. connection con46273; set debug_sync='alter_table_copy_after_lock_upgrade SIGNAL alter_table_locked WAIT_FOR alter_go'; --send alter table t1 add column e int, rename to t2; --echo # --echo # Switching to connection 'default'. connection default; set debug_sync='now WAIT_FOR alter_table_locked'; set debug_sync='mdl_acquire_lock_wait SIGNAL alter_go'; --echo # The below statement should get ER_LOCK_DEADLOCK error --echo # (i.e. it should not allow ALTER to proceed, and then --echo # fail due to 't1' changing its name to 't2'). --error ER_LOCK_DEADLOCK update t1 set c3=c3+1 where c2 = 3; --echo # --echo # Switching to connection 'con46273'. connection con46273; --echo # Reap ALTER TABLE. --reap --echo # --echo # Switching to connection 'default'. connection default; disconnect con46273; --echo # Clean-up. set debug_sync= 'RESET'; drop table t2; --echo # --echo # Test for bug #46673 "Deadlock between FLUSH TABLES WITH READ LOCK --echo # and DML". --echo # --disable_warnings drop tables if exists t1; --enable_warnings connect (con46673, localhost, root,,); connection default; create table t1 (i int); --echo # Switching to connection 'con46673'. connection con46673; begin; insert into t1 values (1); --echo # Switching to connection 'default'. connection default; --echo # Statement below should not get blocked. And if after some --echo # changes to code it is there should not be a deadlock between --echo # it and transaction from connection 'con46673'. flush tables with read lock; unlock tables; --echo # Switching to connection 'con46673'. connection con46673; delete from t1 where i = 1; commit; --echo # Switching to connection 'default'. connection default; --echo # Clean-up disconnect con46673; drop table t1; --echo # --echo # Bug#48210 FLUSH TABLES WITH READ LOCK deadlocks --echo # against concurrent CREATE PROCEDURE --echo # connect (con2, localhost, root); --echo # Test 1: CREATE PROCEDURE --echo # Connection 1 connection default; --echo # Start CREATE PROCEDURE and open mysql.proc SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait'; --send CREATE PROCEDURE p1() SELECT 1 --echo # Connection 2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; --echo # Check that FLUSH must wait to get the GRL --echo # and let CREATE PROCEDURE continue SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL grlwait'; --send FLUSH TABLES WITH READ LOCK --echo # Connection 1 connection default; --reap --echo # Connection 2 connection con2; --reap UNLOCK TABLES; --echo # Connection 1 connection default; SET DEBUG_SYNC= 'RESET'; --echo # Test 2: DROP PROCEDURE connection default; --echo # Start DROP PROCEDURE and open tables SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait'; --send DROP PROCEDURE p1 --echo # Connection 2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; --echo # Check that FLUSH must wait to get the GRL --echo # and let DROP PROCEDURE continue SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL grlwait'; --send FLUSH TABLES WITH READ LOCK --echo # Connection 1 connection default; --echo # Once FLUSH TABLES WITH READ LOCK starts waiting --echo # DROP PROCEDURE will be waked up and will drop --echo # procedure. Global read lock will be granted after --echo # this statement ends. --echo # --echo # Reaping DROP PROCEDURE. --reap --echo # Connection 2 connection con2; --echo # Reaping FTWRL. --reap UNLOCK TABLES; --echo # Connection 1 connection default; SET DEBUG_SYNC= 'RESET'; disconnect con2; --echo # --echo # Bug#50786 Assertion `thd->mdl_context.trans_sentinel() == __null' --echo # failed in open_ltable() --echo # --echo # Supress warnings written to the log file call mtr.add_suppression("Wait on a lock was aborted due to a pending exclusive lock"); --disable_warnings DROP TABLE IF EXISTS t1, t2; --enable_warnings connect (con1,localhost,root); connect (con2,localhost,root); connect (con3,localhost,root); connection default; CREATE TABLE t1 (i INT); CREATE TABLE t2 (i INT); SET @old_general_log= @@global.general_log; SET @@global.general_log= 1; SET @old_log_output= @@global.log_output; SET @@global.log_output= 'TABLE'; SET @old_sql_log_off= @@session.sql_log_off; SET @@session.sql_log_off= 1; --echo # connection: con1 connection con1; HANDLER t1 OPEN; --echo # connection: con3 connection con3; SET @@session.sql_log_off= 1; --echo # connection: con2 connection con2; SET DEBUG_SYNC= 'thr_multi_lock_after_thr_lock SIGNAL parked WAIT_FOR go'; # The below statement will block on the debug sync point # after it gets write lock on mysql.general_log table. --echo # Sending: --send SELECT 1 --echo # connection: con3 connection con3; SET DEBUG_SYNC= 'now WAIT_FOR parked'; --echo # connection: con1 connection con1; # This statement will block in open_ltable() when # trying to write into mysql.general_log. --echo # Sending: --send SELECT 1 --echo # connection: con3 connection con3; let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for table level lock" and info = "SELECT 1"; --source include/wait_condition.inc # The ALTER below will try to abort the statement in connection con1, # since the latter waits on a table-level lock while having a HANDLER # open. This will cause mysql_lock_tables() in con1 fail which before # triggered the assert. ALTER TABLE t1 ADD COLUMN j INT; --echo # connection: default connection default; SET DEBUG_SYNC= 'now SIGNAL go'; --echo # connection: con1 connection con1; --echo # Reaping SELECT 1 --reap HANDLER t1 CLOSE; --echo # connection: con2 connection con2; --echo # Reaping SELECT 1 --reap --echo # connection: default connection default; DROP TABLE t1, t2; SET DEBUG_SYNC= 'RESET'; disconnect con1; disconnect con2; disconnect con3; SET @@global.general_log= @old_general_log; SET @@global.log_output= @old_log_output; SET @@session.sql_log_off= @old_sql_log_off; --echo # --echo # Additional coverage for bug #50913 "Deadlock between --echo # open_and_lock_tables_derived and MDL". The main test --echo # case is in lock_multi.test --echo # --disable_warnings drop table if exists t1; --enable_warnings set debug_sync= 'RESET'; connect (con50913_1,localhost,root); connect (con50913_2,localhost,root); connection default; create table t1 (i int) engine=InnoDB; --echo # Switching to connection 'con50913_1'. connection con50913_1; set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL parked WAIT_FOR go'; --echo # Sending: --send alter table t1 add column j int, ALGORITHM=COPY --echo # Switching to connection 'default'. connection default; --echo # Wait until ALTER TABLE gets blocked on a sync point after --echo # acquiring thr_lock.c lock. set debug_sync= 'now WAIT_FOR parked'; --echo # The below statement should wait on MDL lock and not deadlock on --echo # thr_lock.c lock. --echo # Sending: --send truncate table t1 --echo # Switching to connection 'con50913_2'. connection con50913_2; --echo # Wait until TRUNCATE TABLE is blocked on MDL lock. let $wait_condition= select count(*) = 1 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "truncate table t1"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE. set debug_sync= 'now SIGNAL go'; --echo # Switching to connection 'con50913_1'. connection con50913_1; --echo # Reaping ALTER TABLE. --reap --echo # Switching to connection 'default'. connection default; --echo # Reaping TRUNCATE TABLE. --reap disconnect con50913_1; disconnect con50913_2; set debug_sync= 'RESET'; drop table t1; --echo # --echo # Test for bug #50998 "Deadlock in MDL code during test --echo # rqg_mdl_stability". --echo # Also provides coverage for the case when addition of --echo # waiting statement adds several loops in the waiters --echo # graph and therefore several searches for deadlock --echo # should be performed. --disable_warnings drop table if exists t1; --enable_warnings set debug_sync= 'RESET'; connect (con1,localhost,root); connect (con2,localhost,root); connect (con3,localhost,root); connection default; create table t1 (i int); --echo # Switching to connection 'con1'. connection con1; begin; select * from t1; --echo # Switching to connection 'con2'. connection con2; begin; select * from t1; --echo # Switching to connection 'default'. connection default; --echo # Start ALTER TABLE which will acquire SNW lock and --echo # table lock and get blocked on sync point. set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL parked WAIT_FOR go'; --echo # Sending: --send alter table t1 add column j int --echo # Switching to connection 'con1'. connection con1; --echo # Wait until ALTER TABLE gets blocked on a sync point. set debug_sync= 'now WAIT_FOR parked'; --echo # Sending: --send insert into t1 values (1) --echo # Switching to connection 'con2'. connection con2; --echo # Sending: --send insert into t1 values (1) --echo # Switching to connection 'con3'. connection con3; --echo # Wait until both 'con1' and 'con2' are blocked trying to acquire --echo # SW lock on the table. let $wait_condition= select count(*) = 2 from information_schema.processlist where state = "Waiting for table metadata lock" and info = "insert into t1 values (1)"; --source include/wait_condition.inc --echo # Unblock ALTER TABLE. Since it will try to upgrade SNW to X lock --echo # deadlock with two loops in waiting graph will occur. Both loops --echo # should be found and DML statements in both 'con1' and 'con2' --echo # should be aborted with ER_LOCK_DEADLOCK errors. set debug_sync= 'now SIGNAL go'; --echo # Switching to connection 'con1'. connection con1; --echo # Reaping INSERT. It should end with ER_LOCK_DEADLOCK error and --echo # not wait indefinitely (as it happened before the bugfix). --error ER_LOCK_DEADLOCK --reap commit; --echo # Switching to connection 'con2'. connection con2; --echo # Reaping INSERT. --error ER_LOCK_DEADLOCK --reap commit; --echo # Switching to connection 'default'. connection default; --echo # Reap ALTER TABLE. --reap disconnect con1; disconnect con2; disconnect con3; connection default; set debug_sync= 'RESET'; drop table t1; --echo # --echo # Bug#42643: InnoDB does not support replication of TRUNCATE TABLE --echo # --echo # Ensure that a acquired lock is not given up due to a conflict. --echo # connect (con1,localhost,root,,test,,); connect (con2,localhost,root,,test,,); connect (con3,localhost,root,,test,,); connection default; --disable_warnings DROP TABLE IF EXISTS t1; --enable_warnings CREATE TABLE t1 (a INT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1),(2),(3); --echo # Connection: con1 connection con1; LOCK TABLES t1 WRITE; SET debug_sync='upgrade_lock_for_truncate SIGNAL parked_truncate WAIT_FOR go_truncate'; send TRUNCATE TABLE t1; connection default; --echo # Connection: default SET debug_sync='now WAIT_FOR parked_truncate'; connection con2; --echo # Connection: con2 SET debug_sync='after_open_table_ignore_flush SIGNAL parked_show WAIT_FOR go_show'; send SHOW FIELDS FROM t1; connection default; --echo # Connection: default SET debug_sync='now WAIT_FOR parked_show'; connection con3; --echo # Connection: con3 SET debug_sync='after_flush_unlock SIGNAL parked_flush WAIT_FOR go_flush'; send FLUSH TABLES t1; connection default; --echo # Connection: default SET debug_sync='now WAIT_FOR parked_flush'; SET debug_sync='now SIGNAL go_truncate'; --echo # Ensure that truncate waits for a exclusive lock let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for table metadata lock' AND info='TRUNCATE TABLE t1'; --source include/wait_condition.inc SET debug_sync= 'now SIGNAL go_show'; connection con1; --echo # Connection: con1 (TRUNCATE) --echo # Reaping... reap; UNLOCK TABLES; connection con2; --echo # Connection: con2 (SHOW FIELDS FROM t1) --echo # Reaping... reap; connection default; --echo # Connection: default SET debug_sync= 'now SIGNAL go_flush'; connection con3; --echo # Connection: con3 (FLUSH TABLES t1) --echo # Reaping... reap; disconnect con1; disconnect con2; disconnect con3; connection default; --echo # Connection: default SET debug_sync= 'RESET'; DROP TABLE t1; --echo # --echo # Bug#52856 concurrent show columns or show full columns causes a crash!!! --echo # CREATE TABLE t1(a CHAR(255)); connect(con1, localhost, root); SET DEBUG_SYNC= "get_schema_column SIGNAL waiting WAIT_FOR completed"; --send SHOW FULL COLUMNS FROM t1 connection default; SET DEBUG_SYNC= "now WAIT_FOR waiting"; --replace_column 8 # SHOW FULL COLUMNS FROM t1; SET DEBUG_SYNC= "now SIGNAL completed"; --replace_column 8 # connection con1; --reap connection default; DROP TABLE t1; disconnect con1; --echo # --echo # Tests for schema-scope locks --echo # --disable_warnings DROP DATABASE IF EXISTS db1; DROP DATABASE IF EXISTS db2; --enable_warnings connect (con2, localhost, root); connect (con3, localhost, root); --echo # Test 1: --echo # CREATE DATABASE blocks database DDL on the same database, but --echo # not database DDL on different databases. Tests X vs X lock. --echo # --echo # Connection default connection default; SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send CREATE DATABASE db1 --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should block. --send CREATE DATABASE db1 --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='CREATE DATABASE db1'; --source include/wait_condition.inc # This should not block. CREATE DATABASE db2; ALTER DATABASE db2 DEFAULT CHARACTER SET utf8; DROP DATABASE db2; SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: CREATE DATABASE db1 --reap --echo # Connection con2 connection con2; --echo # Reaping: CREATE DATABASE db1 --error ER_DB_CREATE_EXISTS --reap --echo # Test 2: --echo # ALTER DATABASE blocks database DDL on the same database, but --echo # not database DDL on different databases. Tests X vs X lock. --echo # --echo # Connection default connection default; SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should block. --send ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='ALTER DATABASE db1 DEFAULT CHARACTER SET utf8'; --source include/wait_condition.inc # This should not block. CREATE DATABASE db2; ALTER DATABASE db2 DEFAULT CHARACTER SET utf8; DROP DATABASE db2; SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 --reap --echo # Connection con2 connection con2; --echo # Reaping: ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 --reap --echo # Connection default connection default; SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should also block. --send DROP DATABASE db1 --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='DROP DATABASE db1'; --source include/wait_condition.inc SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 --reap --echo # Connection con2 connection con2; --echo # Reaping: DROP DATABASE db1 --reap # Recreate the database CREATE DATABASE db1; --echo # Test 3: --echo # Two ALTER..UPGRADE of the same database are mutually exclusive, but --echo # two ALTER..UPGRADE of different databases are not. Tests X vs X lock. --echo # let $MYSQLD_DATADIR= `select @@datadir`; # Manually make a 5.0 database from the template --mkdir $MYSQLD_DATADIR/a-b-c --copy_file $MYSQLD_DATADIR/db1/db.opt $MYSQLD_DATADIR/a-b-c/db.opt --mkdir $MYSQLD_DATADIR/a-b-c-d --copy_file $MYSQLD_DATADIR/db1/db.opt $MYSQLD_DATADIR/a-b-c-d/db.opt --echo # Connection default connection default; SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send ALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should block. --send ALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='ALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME'; --source include/wait_condition.inc # This should not block. ALTER DATABASE `#mysql50#a-b-c-d` UPGRADE DATA DIRECTORY NAME; SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: ALTER DATABASE '#mysql50#a-b-c' UPGRADE DATA DIRECTORY NAME --reap --echo # Connection con2 connection con2; --echo # Reaping: ALTER DATABASE '#mysql50#a-b-c' UPGRADE DATA DIRECTORY NAME --error ER_BAD_DB_ERROR --reap DROP DATABASE `a-b-c`; DROP DATABASE `a-b-c-d`; --echo # Test 4: --echo # DROP DATABASE blocks database DDL on the same database, but --echo # not database DDL on different databases. Tests X vs X lock. --echo # --echo # Connection default connection default; SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send DROP DATABASE db1 --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should block. --send DROP DATABASE db1 --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='DROP DATABASE db1'; --source include/wait_condition.inc # This should not block. CREATE DATABASE db2; ALTER DATABASE db2 DEFAULT CHARACTER SET utf8; DROP DATABASE db2; SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: DROP DATABASE db1 --reap --echo # Connection con2 connection con2; --echo # Reaping: DROP DATABASE db1 --error ER_DB_DROP_EXISTS --reap --echo # Connection default connection default; CREATE DATABASE db1; SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send DROP DATABASE db1 --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should also block. --send ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='ALTER DATABASE db1 DEFAULT CHARACTER SET utf8'; --source include/wait_condition.inc SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: DROP DATABASE db1 --reap --echo # Connection con2 connection con2; --echo # Reaping: ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 # Error 1 is from ALTER DATABASE when the database does not exist. # Listing the error twice to prevent result diffences based on filename. --error 1,1 --reap --echo # Test 5: --echo # Locked database name prevents CREATE of tables in that database. --echo # Tests X vs IX lock. --echo # --echo # Connection default connection default; CREATE DATABASE db1; SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send DROP DATABASE db1 --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should block. --send CREATE TABLE db1.t1 (a INT) --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='CREATE TABLE db1.t1 (a INT)'; --source include/wait_condition.inc SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: DROP DATABASE db1 --reap --echo # Connection con2 connection con2; --echo # Reaping: CREATE TABLE db1.t1 (a INT) --error ER_BAD_DB_ERROR --reap --echo # Test 6: --echo # Locked database name prevents RENAME of tables to/from that database. --echo # Tests X vs IX lock. --echo # --echo # Connection default connection default; CREATE DATABASE db1; CREATE TABLE db1.t1 (a INT); SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send DROP DATABASE db1 --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should block. --send RENAME TABLE db1.t1 TO test.t1 --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='RENAME TABLE db1.t1 TO test.t1'; --source include/wait_condition.inc SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: DROP DATABASE db1 --reap --echo # Connection con2 connection con2; --echo # Reaping: RENAME TABLE db1.t1 TO test.t1 --error ER_FILE_NOT_FOUND, ER_FILE_NOT_FOUND --reap --echo # Connection default connection default; CREATE DATABASE db1; CREATE TABLE test.t2 (a INT); SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send DROP DATABASE db1 --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should block. --send RENAME TABLE test.t2 TO db1.t2 --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='RENAME TABLE test.t2 TO db1.t2'; --source include/wait_condition.inc SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: DROP DATABASE db1 --reap --echo # Connection con2 connection con2; --echo # Reaping: RENAME TABLE test.t2 TO db1.t2 # Error 7 is from RENAME TABLE where the target database does not exist. # Listing the error twice to prevent result diffences based on filename. --error 7, 7 --reap DROP TABLE test.t2; --echo # Test 7: --echo # Locked database name prevents DROP of tables in that database. --echo # Tests X vs IX lock. --echo # --echo # Connection default connection default; CREATE DATABASE db1; CREATE TABLE db1.t1 (a INT); SET DEBUG_SYNC= 'after_wait_locked_schema_name SIGNAL locked WAIT_FOR blocked'; --echo # Sending: --send DROP DATABASE db1 --echo # Connection con2 connection con2; SET DEBUG_SYNC= 'now WAIT_FOR locked'; --echo # Sending: # This should block. --send DROP TABLE db1.t1 --echo # Connection con3 connection con3; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for schema metadata lock' AND info='DROP TABLE db1.t1'; --source include/wait_condition.inc SET DEBUG_SYNC= 'now SIGNAL blocked'; --echo # Connection default connection default; --echo # Reaping: DROP DATABASE db1 --reap --echo # Connection con2 connection con2; --echo # Reaping: DROP TABLE db1.t1 --error ER_BAD_TABLE_ERROR --reap --echo # Connection default connection default; disconnect con2; disconnect con3; SET DEBUG_SYNC= 'RESET'; --echo # --echo # End of tests for schema-scope locks --echo # --echo # --echo # Tests of granted global S lock (FLUSH TABLE WITH READ LOCK) --echo # CREATE DATABASE db1; CREATE TABLE db1.t1(a INT); connect(con2, localhost, root); connect(con3, localhost, root); --echo # Connection default connection default; FLUSH TABLE WITH READ LOCK; --echo # Connection con2 connection con2; # IX global lock should block --send CREATE TABLE db1.t2(a INT) --echo # Connection default connection default; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for global read lock' AND info='CREATE TABLE db1.t2(a INT)'; --source include/wait_condition.inc UNLOCK TABLES; --echo # Connection con2 connection con2; --echo # Reaping CREATE TABLE db1.t2(a INT) --reap --echo # Connection default connection default; FLUSH TABLE WITH READ LOCK; --echo # Connection con2 connection con2; # X global lock should block --send ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 --echo # Connection default connection default; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE state='Waiting for global read lock' AND info='ALTER DATABASE db1 DEFAULT CHARACTER SET utf8'; --source include/wait_condition.inc UNLOCK TABLES; --echo # Connection con2 connection con2; --echo # Reaping ALTER DATABASE db1 DEFAULT CHARACTER SET utf8 --reap --echo # Connection default connection default; FLUSH TABLE WITH READ LOCK; --echo # Connection con2 connection con2; # S global lock should not block FLUSH TABLE WITH READ LOCK; UNLOCK TABLES; --echo # Connection default connection default; UNLOCK TABLES; DROP DATABASE db1; disconnect con2; disconnect con3; --echo # --echo # Bug#56292 Deadlock with ALTER TABLE and MERGE tables --echo # --disable_warnings DROP TABLE IF EXISTS t1, t2, m1; --enable_warnings CREATE TABLE t1(a INT) engine=MyISAM; CREATE TABLE t2(a INT) engine=MyISAM; CREATE TABLE m1(a INT) engine=MERGE UNION=(t1, t2); INSERT INTO t1 VALUES (1), (2); INSERT INTO t2 VALUES (3), (4); connect(con1, localhost, root); connect(con2, localhost, root); --echo # Connection con1 connection con1; --echo # We need EXECUTE 2 since ALTER TABLE does SU => SNW => X and we want --echo # to stop at the second upgrade. SET DEBUG_SYNC= 'mdl_upgrade_lock SIGNAL upgrade WAIT_FOR continue EXECUTE 2'; --echo # Sending: --send ALTER TABLE m1 engine=MERGE UNION=(t2, t1) --echo # Connection con2 connection con2; --echo # Waiting for ALTER TABLE to try lock upgrade SET DEBUG_SYNC= 'now WAIT_FOR upgrade'; SET DEBUG_SYNC= 'now SIGNAL continue'; SET DEBUG_SYNC= 'now WAIT_FOR upgrade'; --echo # Sending: --send DELETE FROM t2 WHERE a = 3 --echo # Connection default connection default; --echo # Check that DELETE is waiting on a metadata lock and not a table lock. let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for table metadata lock" AND info = "DELETE FROM t2 WHERE a = 3"; --source include/wait_condition.inc --echo # Now that DELETE blocks on a metadata lock, we should be able to do --echo # SELECT * FROM m1 here. SELECT used to be blocked by a DELETE table --echo # lock request. SELECT * FROM m1; --echo # Resuming ALTER TABLE SET DEBUG_SYNC= 'now SIGNAL continue'; --echo # Connection con1 connection con1; --echo # Reaping: ALTER TABLE m1 engine=MERGE UNION=(t2, t1) --reap --echo # Connection con2 connection con2; --echo # Reaping: DELETE FROM t2 WHERE a = 3 --reap --echo # Connection default connection default; DROP TABLE m1, t1, t2; SET DEBUG_SYNC= 'RESET'; disconnect con1; disconnect con2; --echo # --echo # Bug#21021848 ASSERTION `M_STATUS == DA_ERROR' FAILED. --echo # CREATE TABLE t1(c1 INT NOT NULL) ENGINE = csv; CREATE TABLE t2(c1 INT NOT NULL); --echo # Emulate corruption of t1 LOCK TABLES t1 WRITE; INSERT INTO t1 VALUES(0); CHECK TABLE t1; UNLOCK TABLES; --echo # Start XA txn on default XA START 'test2'; --echo # Acquire SR on t2 SELECT * FROM t2; --echo # Block IS query just before calling lock_table_names() (before X on t1) SET DEBUG_SYNC='recover_ot_repair SIGNAL parked WAIT_FOR go'; --send SELECT COUNT(*) > 1 FROM information_schema.key_column_usage --echo # Create a new conncection which will compete for MDL lock --connect (con1,localhost,root,,) --echo # Wait until default becomes blocked SET DEBUG_SYNC='now WAIT_FOR parked'; --echo # Try to acquire X on t1 and t2, which will block while default --echo # holds SR on t2 --send DROP TABLES t1, t2 --echo # Create control connection --connect (con2,localhost,root,,) --echo # Wait until con1 is blocked 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 # Wake up XA txn/IS query on default SET DEBUG_SYNC='now SIGNAL go'; --echo # Disconnect control connection --disconnect con2 --source include/wait_until_disconnected.inc --echo # Switch to default connection --connection default --echo # Wait for IS query which will try repair t1 which requires X. --echo # Previously that resulted in deadlock with con1 over t1, --echo # but now t1 is skipped and a warning is issued --reap --echo # Finish XA txn 'test2' to release SR on t2 so that con1 --echo # becomes unblocked XA END 'test2'; XA PREPARE 'test2'; XA COMMIT 'test2'; --echo # Cleanup SET DEBUG_SYNC= 'RESET'; --echo # Clean up con1 now that the XA txn has finished --connection con1 --echo # Wait for the now unblocked DROP t1, t2 to complete --reap --echo # Disconnecting con1 --disconnect con1 --source include/wait_until_disconnected.inc --echo # Switching to back to default at end of test case --connection default --echo # --echo # Bug#26739438 DEADLOCK ON GET_LOCK(..., 0) --echo # --echo # Run GET_LOCK(...,0) from two connections to which would previously --echo # cause deadlock CREATE TABLE t1(i INT); INSERT INTO t1 VALUES (0), (1); --echo # Starting con0 connect (con0,localhost,root,,test,,); SELECT i FROM t1 WHERE i = 0 AND GET_LOCK(i, 0); --echo # Starting con1 connect (con1,localhost,root,,test,,); SELECT i FROM t1 WHERE i = 1 AND GET_LOCK(i, 0); --echo # Send query which will do a 0-wait on i=0 while holding lock on i=1 SET DEBUG_SYNC='mdl_acquire_lock_wait SIGNAL wait0 WAIT_FOR go0'; --send SELECT i FROM t1 WHERE GET_LOCK(i, 0) AND i = 0 --echo # Switch to con0. Send query which will do a 0-wait on i=1 while --echo # holding lock on i=0 connection con0; SET DEBUG_SYNC='mdl_acquire_lock_wait SIGNAL wait1 WAIT_FOR go1'; --send SELECT i FROM t1 WHERE GET_LOCK(i, 0) AND i = 1 --echo # Switch to default connection and wait until both con0 and con1 --echo # are ready to check for deadlocks connection default; SET DEBUG_SYNC='now WAIT_FOR wait0'; SET DEBUG_SYNC='now WAIT_FOR wait1'; --echo # Tell both connections to proceed SET DEBUG_SYNC='now SIGNAL go0'; SET DEBUG_SYNC='now SIGNAL go1'; --echo # Wait for con0 connection con0; --reap --echo # Wait for con1 (should not deadlock) connection con1; --reap connection default; disconnect con0; disconnect con1; DROP TABLE t1; # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc