# # We need the Debug Sync Facility. # --source include/have_debug_sync.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_shared_lock_to_exclusive 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_exclusive_locks_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 # 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' 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' 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_exclusive_locks_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_exclusive_locks_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); --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 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 = "Table 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'. 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 = "Table 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" 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 = "Table 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" 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 = "Table 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" 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 #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; # 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