初版
This commit is contained in:
644
build/lib/mysql/mysql-test/t/lock_multi.test
Normal file
644
build/lib/mysql/mysql-test/t/lock_multi.test
Normal file
@@ -0,0 +1,644 @@
|
||||
-- source include/not_embedded.inc
|
||||
|
||||
# Save the initial number of concurrent sessions
|
||||
--source include/count_sessions.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1,t2;
|
||||
--enable_warnings
|
||||
|
||||
# Test to see if select will get the lock ahead of low priority update
|
||||
|
||||
connect (locker,localhost,root,,);
|
||||
connect (reader,localhost,root,,);
|
||||
connect (writer,localhost,root,,);
|
||||
|
||||
connection locker;
|
||||
create table t1(n int);
|
||||
insert into t1 values (1);
|
||||
lock tables t1 write;
|
||||
connection writer;
|
||||
send
|
||||
update low_priority t1 set n = 4;
|
||||
connection reader;
|
||||
# Sleep a bit till the update of connection writer is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Locked" and info = "update low_priority t1 set n = 4";
|
||||
--source include/wait_condition.inc
|
||||
send
|
||||
select n from t1;
|
||||
connection locker;
|
||||
# Sleep a bit till the select of connection reader is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Locked" and info = "select n from t1";
|
||||
--source include/wait_condition.inc
|
||||
unlock tables;
|
||||
connection writer;
|
||||
reap;
|
||||
connection reader;
|
||||
reap;
|
||||
drop table t1;
|
||||
|
||||
connection locker;
|
||||
create table t1(n int);
|
||||
insert into t1 values (1);
|
||||
lock tables t1 read;
|
||||
connection writer;
|
||||
send
|
||||
update low_priority t1 set n = 4;
|
||||
connection reader;
|
||||
# Sleep a bit till the update of connection writer is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Locked" and info = "update low_priority t1 set n = 4";
|
||||
--source include/wait_condition.inc
|
||||
select n from t1;
|
||||
connection locker;
|
||||
unlock tables;
|
||||
connection writer;
|
||||
reap;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Test problem when using locks with multi-updates
|
||||
# It should not block when multi-update is reading on a read-locked table
|
||||
#
|
||||
|
||||
connection locker;
|
||||
create table t1 (a int, b int);
|
||||
create table t2 (c int, d int);
|
||||
insert into t1 values(1,1);
|
||||
insert into t1 values(2,2);
|
||||
insert into t2 values(1,2);
|
||||
lock table t1 read;
|
||||
connection writer;
|
||||
update t1,t2 set c=a where b=d;
|
||||
connection reader;
|
||||
select c from t2;
|
||||
connection locker;
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
|
||||
#
|
||||
# Test problem when using locks on many tables and dropping a table that
|
||||
# is to-be-locked by another thread
|
||||
#
|
||||
#
|
||||
connection locker;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
lock table t1 write, t2 write;
|
||||
connection reader;
|
||||
send
|
||||
insert t1 select * from t2;
|
||||
connection locker;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Locked" and info = "insert t1 select * from t2";
|
||||
--source include/wait_condition.inc
|
||||
drop table t2;
|
||||
connection reader;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
reap;
|
||||
connection locker;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Same test as above, but with the dropped table locked twice
|
||||
#
|
||||
|
||||
connection locker;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
lock table t1 write, t2 write, t1 as t1_2 write, t2 as t2_2 write;
|
||||
connection reader;
|
||||
send
|
||||
insert t1 select * from t2;
|
||||
connection locker;
|
||||
# Sleep a bit till the insert of connection reader is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Locked" and info = "insert t1 select * from t2";
|
||||
--source include/wait_condition.inc
|
||||
drop table t2;
|
||||
connection reader;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
reap;
|
||||
connection locker;
|
||||
drop table t1;
|
||||
|
||||
|
||||
--echo End of 4.1 tests
|
||||
|
||||
#
|
||||
# Bug#9998 MySQL client hangs on USE "database"
|
||||
#
|
||||
create table t1(a int);
|
||||
lock tables t1 write;
|
||||
connection reader;
|
||||
show columns from t1;
|
||||
connection locker;
|
||||
unlock tables;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#16986 Deadlock condition with MyISAM tables
|
||||
#
|
||||
|
||||
# Need a matching user in mysql.user for multi-table select
|
||||
--source include/add_anonymous_users.inc
|
||||
|
||||
connection locker;
|
||||
USE mysql;
|
||||
LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE;
|
||||
FLUSH TABLES;
|
||||
#
|
||||
connection reader;
|
||||
USE mysql;
|
||||
# Note: This must be a multi-table select, otherwise the deadlock will not occur
|
||||
send
|
||||
SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
|
||||
#
|
||||
connection locker;
|
||||
# Sleep a bit till the select of connection reader is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for table" and info =
|
||||
"SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1";
|
||||
--source include/wait_condition.inc
|
||||
# Make test case independent from earlier grants.
|
||||
--replace_result "Table is already up to date" "OK"
|
||||
OPTIMIZE TABLES columns_priv, db, host, user;
|
||||
UNLOCK TABLES;
|
||||
#
|
||||
connection reader;
|
||||
reap;
|
||||
USE test;
|
||||
#
|
||||
connection locker;
|
||||
use test;
|
||||
#
|
||||
connection default;
|
||||
#
|
||||
# Test if CREATE TABLE with LOCK TABLE deadlocks.
|
||||
#
|
||||
connection writer;
|
||||
CREATE TABLE t1 (c1 int);
|
||||
LOCK TABLE t1 WRITE;
|
||||
#
|
||||
# This waits until t1 is unlocked.
|
||||
connection locker;
|
||||
send
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
#
|
||||
connection writer;
|
||||
# Sleep a bit till the flush of connection locker is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Flushing tables" and info = "FLUSH TABLES WITH READ LOCK";
|
||||
--source include/wait_condition.inc
|
||||
# This must not block.
|
||||
CREATE TABLE t2 (c1 int);
|
||||
UNLOCK TABLES;
|
||||
#
|
||||
# This awakes now.
|
||||
connection locker;
|
||||
reap;
|
||||
UNLOCK TABLES;
|
||||
#
|
||||
connection default;
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Test if CREATE TABLE SELECT with LOCK TABLE deadlocks.
|
||||
#
|
||||
connection writer;
|
||||
CREATE TABLE t1 (c1 int);
|
||||
LOCK TABLE t1 WRITE;
|
||||
#
|
||||
# This waits until t1 is unlocked.
|
||||
connection locker;
|
||||
send
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
#
|
||||
# This must not block.
|
||||
connection writer;
|
||||
# Sleep a bit till the flush of connection locker is in work and hangs
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Flushing tables" and info = "FLUSH TABLES WITH READ LOCK";
|
||||
--source include/wait_condition.inc
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
CREATE TABLE t2 AS SELECT * FROM t1;
|
||||
UNLOCK TABLES;
|
||||
#
|
||||
# This awakes now.
|
||||
connection locker;
|
||||
reap;
|
||||
UNLOCK TABLES;
|
||||
#
|
||||
connection default;
|
||||
DROP TABLE t1;
|
||||
|
||||
--source include/delete_anonymous_users.inc
|
||||
|
||||
#
|
||||
# Bug#19815 CREATE/RENAME/DROP DATABASE can deadlock on a global read lock
|
||||
#
|
||||
connect (con1,localhost,root,,);
|
||||
connect (con2,localhost,root,,);
|
||||
#
|
||||
connection con1;
|
||||
CREATE DATABASE mysqltest_1;
|
||||
FLUSH TABLES WITH READ LOCK;
|
||||
#
|
||||
# With bug in place: acquire LOCK_mysql_create_table and
|
||||
# wait in wait_if_global_read_lock().
|
||||
connection con2;
|
||||
send
|
||||
DROP DATABASE mysqltest_1;
|
||||
#
|
||||
# With bug in place: try to acquire LOCK_mysql_create_table...
|
||||
# When fixed: Reject dropping db because of the read lock.
|
||||
connection con1;
|
||||
# Wait a bit so that the session con2 is in state "Waiting for release of readlock"
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for release of readlock"
|
||||
and info = "DROP DATABASE mysqltest_1";
|
||||
--source include/wait_condition.inc
|
||||
--error ER_CANT_UPDATE_WITH_READLOCK
|
||||
DROP DATABASE mysqltest_1;
|
||||
UNLOCK TABLES;
|
||||
#
|
||||
connection con2;
|
||||
reap;
|
||||
#
|
||||
connection default;
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
# This must have been dropped by connection 2 already,
|
||||
# which waited until the global read lock was released.
|
||||
--error ER_DB_DROP_EXISTS
|
||||
DROP DATABASE mysqltest_1;
|
||||
|
||||
#
|
||||
# Bug#17264 MySQL Server freeze
|
||||
#
|
||||
connection locker;
|
||||
# Disable warnings to allow test to run also without InnoDB
|
||||
--disable_warnings
|
||||
create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) engine=innodb;
|
||||
--enable_warnings
|
||||
lock tables t1 write;
|
||||
connection writer;
|
||||
send
|
||||
alter table t1 auto_increment=0;
|
||||
connection reader;
|
||||
# Wait till connection writer is blocked
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Locked" and info = "alter table t1 auto_increment=0";
|
||||
--source include/wait_condition.inc
|
||||
send
|
||||
alter table t1 auto_increment=0;
|
||||
connection locker;
|
||||
# Wait till connection reader is blocked
|
||||
let $wait_condition=
|
||||
select count(*) = 2 from information_schema.processlist
|
||||
where state = "Locked" and info = "alter table t1 auto_increment=0";
|
||||
--source include/wait_condition.inc
|
||||
unlock tables;
|
||||
connection writer;
|
||||
reap;
|
||||
connection reader;
|
||||
reap;
|
||||
connection locker;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#43230: SELECT ... FOR UPDATE can hang with FLUSH TABLES WITH READ LOCK indefinitely
|
||||
#
|
||||
|
||||
connect (con1,localhost,root,,);
|
||||
connect (con2,localhost,root,,);
|
||||
connect (con3,localhost,root,,);
|
||||
connect (con4,localhost,root,,);
|
||||
connect (con5,localhost,root,,);
|
||||
|
||||
create table t1 (a int);
|
||||
create table t2 like t1;
|
||||
|
||||
connection con1;
|
||||
--echo # con1
|
||||
lock tables t1 write;
|
||||
connection con2;
|
||||
--echo # con2
|
||||
send flush tables with read lock;
|
||||
connection con5;
|
||||
--echo # con5
|
||||
let $show_statement= SHOW PROCESSLIST;
|
||||
let $field= State;
|
||||
let $condition= = 'Flushing tables';
|
||||
--source include/wait_show_condition.inc
|
||||
--echo # global read lock is taken
|
||||
connection con3;
|
||||
--echo # con3
|
||||
send select * from t2 for update;
|
||||
connection con5;
|
||||
let $show_statement= SHOW PROCESSLIST;
|
||||
let $field= State;
|
||||
let $condition= = 'Waiting for release of readlock';
|
||||
--source include/wait_show_condition.inc
|
||||
--echo # waiting for release of read lock
|
||||
connection con4;
|
||||
--echo # con4
|
||||
--echo # would hang and later cause a deadlock
|
||||
flush tables t2;
|
||||
connection con1;
|
||||
--echo # clean up
|
||||
unlock tables;
|
||||
connection con2;
|
||||
--reap
|
||||
unlock tables;
|
||||
connection con3;
|
||||
--reap
|
||||
connection default;
|
||||
disconnect con5;
|
||||
disconnect con4;
|
||||
disconnect con3;
|
||||
disconnect con2;
|
||||
disconnect con1;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # Lightweight version:
|
||||
--echo # Ensure that the wait for a GRL is done before opening tables.
|
||||
--echo #
|
||||
|
||||
connect (con1,localhost,root,,);
|
||||
connect (con2,localhost,root,,);
|
||||
|
||||
create table t1 (a int);
|
||||
create table t2 like t1;
|
||||
|
||||
--echo #
|
||||
--echo # UPDATE
|
||||
--echo #
|
||||
|
||||
connection default;
|
||||
--echo # default
|
||||
flush tables with read lock;
|
||||
connection con1;
|
||||
--echo # con1
|
||||
send update t2 set a = 1;
|
||||
connection default;
|
||||
--echo # default
|
||||
let $show_statement= SHOW PROCESSLIST;
|
||||
let $field= State;
|
||||
let $condition= = 'Waiting for release of readlock';
|
||||
--source include/wait_show_condition.inc
|
||||
--echo # statement is waiting for release of read lock
|
||||
connection con2;
|
||||
--echo # con2
|
||||
flush table t2;
|
||||
connection default;
|
||||
--echo # default
|
||||
unlock tables;
|
||||
connection con1;
|
||||
--echo # con1
|
||||
--reap
|
||||
|
||||
--echo #
|
||||
--echo # LOCK TABLES .. WRITE
|
||||
--echo #
|
||||
|
||||
connection default;
|
||||
--echo # default
|
||||
flush tables with read lock;
|
||||
connection con1;
|
||||
--echo # con1
|
||||
send lock tables t2 write;
|
||||
connection default;
|
||||
--echo # default
|
||||
let $show_statement= SHOW PROCESSLIST;
|
||||
let $field= State;
|
||||
let $condition= = 'Waiting for release of readlock';
|
||||
--source include/wait_show_condition.inc
|
||||
--echo # statement is waiting for release of read lock
|
||||
connection con2;
|
||||
--echo # con2
|
||||
flush table t2;
|
||||
connection default;
|
||||
--echo # default
|
||||
unlock tables;
|
||||
connection con1;
|
||||
--echo # con1
|
||||
--reap
|
||||
unlock tables;
|
||||
|
||||
connection default;
|
||||
disconnect con2;
|
||||
disconnect con1;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
||||
|
||||
#
|
||||
# Bug#21281 Pending write lock is incorrectly removed when its
|
||||
# statement being KILLed
|
||||
#
|
||||
create table t1 (i int);
|
||||
connection locker;
|
||||
lock table t1 read;
|
||||
connection writer;
|
||||
send
|
||||
update t1 set i= 10;
|
||||
connection reader;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Locked" and info = "update t1 set i= 10";
|
||||
--source include/wait_condition.inc
|
||||
send
|
||||
select * from t1;
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Locked" and info = "select * from t1";
|
||||
--source include/wait_condition.inc
|
||||
let $ID= `select id from information_schema.processlist where state = "Locked" and info = "update t1 set i= 10"`;
|
||||
--replace_result $ID ID
|
||||
eval kill query $ID;
|
||||
connection reader;
|
||||
--reap
|
||||
connection writer;
|
||||
--error ER_QUERY_INTERRUPTED
|
||||
--reap
|
||||
connection locker;
|
||||
unlock tables;
|
||||
connection default;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#25856 HANDLER table OPEN in one connection lock DROP TABLE in another one
|
||||
#
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create table t1 (a int) ENGINE=MEMORY;
|
||||
--echo --> client 2
|
||||
connection locker;
|
||||
--error ER_ILLEGAL_HA
|
||||
handler t1 open;
|
||||
--echo --> client 1
|
||||
connection default;
|
||||
drop table t1;
|
||||
|
||||
|
||||
# Disconnect sessions used in many subtests above
|
||||
disconnect locker;
|
||||
disconnect reader;
|
||||
disconnect writer;
|
||||
|
||||
|
||||
#
|
||||
# Bug#32395 Alter table under a impending global read lock causes a server crash
|
||||
#
|
||||
|
||||
#
|
||||
# Test ALTER TABLE under LOCK TABLES and FLUSH TABLES WITH READ LOCK
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create table t1 (i int);
|
||||
connect (flush,localhost,root,,test,,);
|
||||
connection default;
|
||||
--echo connection: default
|
||||
lock tables t1 write;
|
||||
connection flush;
|
||||
--echo connection: flush
|
||||
--send flush tables with read lock;
|
||||
connection default;
|
||||
--echo connection: default
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Flushing tables";
|
||||
--source include/wait_condition.inc
|
||||
alter table t1 add column j int;
|
||||
connect (insert,localhost,root,,test,,);
|
||||
connection insert;
|
||||
--echo connection: insert
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Flushing tables";
|
||||
--source include/wait_condition.inc
|
||||
--send insert into t1 values (1,2);
|
||||
--echo connection: default
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for release of readlock";
|
||||
--source include/wait_condition.inc
|
||||
unlock tables;
|
||||
connection flush;
|
||||
--echo connection: flush
|
||||
--reap
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Waiting for release of readlock";
|
||||
--source include/wait_condition.inc
|
||||
select * from t1;
|
||||
unlock tables;
|
||||
connection insert;
|
||||
--reap
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from t1;
|
||||
--source include/wait_condition.inc
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
disconnect flush;
|
||||
disconnect insert;
|
||||
|
||||
#
|
||||
# Test that FLUSH TABLES under LOCK TABLES protects write locked tables
|
||||
# from a impending FLUSH TABLES WITH READ LOCK
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create table t1 (i int);
|
||||
connect (flush,localhost,root,,test,,);
|
||||
connection default;
|
||||
--echo connection: default
|
||||
lock tables t1 write;
|
||||
connection flush;
|
||||
--echo connection: flush
|
||||
--send flush tables with read lock;
|
||||
connection default;
|
||||
--echo connection: default
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Flushing tables";
|
||||
--source include/wait_condition.inc
|
||||
flush tables;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Flushing tables";
|
||||
--source include/wait_condition.inc
|
||||
unlock tables;
|
||||
let $wait_condition=
|
||||
select count(*) = 0 from information_schema.processlist
|
||||
where state = "Flushing tables";
|
||||
--source include/wait_condition.inc
|
||||
connection flush;
|
||||
--reap
|
||||
connection default;
|
||||
disconnect flush;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#30331 Table_locks_waited shows inaccurate values
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1,t2;
|
||||
--enable_warnings
|
||||
create table t1 (a int);
|
||||
flush status;
|
||||
lock tables t1 read;
|
||||
let $tlwa= `show status like 'Table_locks_waited'`;
|
||||
connect (waiter,localhost,root,,);
|
||||
connection waiter;
|
||||
--send insert into t1 values(1);
|
||||
connection default;
|
||||
let $wait_condition=
|
||||
select count(*) = 1 from information_schema.processlist
|
||||
where state = "Locked" and info = "insert into t1 values(1)";
|
||||
--source include/wait_condition.inc
|
||||
let $tlwb= `show status like 'Table_locks_waited'`;
|
||||
unlock tables;
|
||||
connection waiter;
|
||||
--reap
|
||||
connection default;
|
||||
drop table t1;
|
||||
disconnect waiter;
|
||||
--disable_query_log
|
||||
eval SET @tlwa= SUBSTRING_INDEX('$tlwa', ' ', -1);
|
||||
eval SET @tlwb= SUBSTRING_INDEX('$tlwb', ' ', -1);
|
||||
--enable_query_log
|
||||
select @tlwa < @tlwb;
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
||||
# Wait till all disconnects are completed
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
||||
Reference in New Issue
Block a user