mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 19:11:46 +01:00
aebaf079d1
The problem is that a SELECT .. FOR UPDATE statement might open a table and later wait for a impeding global read lock without noticing whether it is holding a table that is being waited upon the the flush phase of the process that took the global read lock. The same problem also affected the following statements: LOCK TABLES .. WRITE UPDATE .. SET (update and multi-table update) TRUNCATE TABLE .. LOAD DATA .. The solution is to make the above statements wait for a impending global read lock before opening the tables. If there is no impending global read lock, the statement raises a temporary protection against global read locks and progresses smoothly towards completion. Important notice: the patch does not try to address all possible cases, only those which are common and can be fixed unintrusively enough for 5.0.
818 lines
17 KiB
Text
818 lines
17 KiB
Text
-- 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_timeout= 5;
|
|
let $show_statement= SHOW PROCESSLIST;
|
|
let $field= State;
|
|
let $condition= = 'Locked';
|
|
--source include/wait_show_condition.inc
|
|
send
|
|
select n from t1;
|
|
connection locker;
|
|
# Sleep a bit till the select of connection reader is in work and hangs
|
|
# Here we cannot use include/wait_show_condition.inc because this routine
|
|
# cannot count the number of 'Locked' sessions or access two columns within
|
|
# the same query_get_value call.
|
|
--sleep 3
|
|
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_timeout= 5;
|
|
let $show_statement= SHOW PROCESSLIST;
|
|
let $field= State;
|
|
let $condition= = 'Locked';
|
|
--source include/wait_show_condition.inc
|
|
#
|
|
send
|
|
select n from t1;
|
|
connection locker;
|
|
# Sleep a bit till the select of connection reader is in work and hangs
|
|
# Here we cannot use include/wait_show_condition.inc.
|
|
--sleep 3
|
|
#
|
|
unlock tables;
|
|
connection writer;
|
|
reap;
|
|
connection reader;
|
|
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;
|
|
send
|
|
update t1,t2 set c=a where b=d;
|
|
connection reader;
|
|
# Sleep a bit till the update of connection writer is finished
|
|
# Here we cannot use include/wait_show_condition.inc.
|
|
--sleep 3
|
|
#
|
|
select c from t2;
|
|
connection writer;
|
|
reap;
|
|
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;
|
|
# Sleep a bit till the insert of connection reader is in work and hangs
|
|
let $wait_timeout= 5;
|
|
let $show_statement= SHOW PROCESSLIST;
|
|
let $field= State;
|
|
let $condition= = 'Locked';
|
|
--source include/wait_show_condition.inc
|
|
drop table t2;
|
|
connection reader;
|
|
--error ER_NO_SUCH_TABLE
|
|
reap;
|
|
connection locker;
|
|
drop table t1;
|
|
|
|
# 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#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_timeout= 5;
|
|
let $show_statement= SHOW PROCESSLIST;
|
|
let $field= State;
|
|
let $condition= = 'Waiting for release of readlock';
|
|
--source include/wait_show_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#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_timeout= 5;
|
|
let $show_statement= SHOW PROCESSLIST;
|
|
let $field= State;
|
|
let $condition= = 'Locked';
|
|
--source include/wait_show_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;
|
|
#
|
|
# This must not block.
|
|
connection writer;
|
|
# Sleep a bit till the flush of connection locker is in work and hangs
|
|
let $wait_timeout= 5;
|
|
let $show_statement= SHOW PROCESSLIST;
|
|
let $field= State;
|
|
let $condition= = 'Flushing tables';
|
|
--source include/wait_show_condition.inc
|
|
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_timeout= 5;
|
|
let $show_statement= SHOW PROCESSLIST;
|
|
let $field= State;
|
|
let $condition= = 'Flushing tables';
|
|
--source include/wait_show_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#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;
|
|
# mleich: I have doubts if the next sleep is really necessary
|
|
# Therefore I set it to comment but don't remove it
|
|
# in case it hat to be enabled again.
|
|
# --sleep 2
|
|
delimiter //;
|
|
send
|
|
alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
|
|
delimiter ;//
|
|
connection reader;
|
|
# Wait till connection writer is blocked
|
|
let $wait_timeout= 5;
|
|
let $show_statement= SHOW PROCESSLIST;
|
|
let $field= State;
|
|
let $condition= = 'Locked';
|
|
--source include/wait_show_condition.inc
|
|
delimiter //;
|
|
send
|
|
alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
|
|
delimiter ;//
|
|
connection locker;
|
|
# Wait till connection reader is blocked
|
|
# Here we cannot use include/wait_show_condition.inc.
|
|
--sleep 3
|
|
unlock tables;
|
|
connection writer;
|
|
reap;
|
|
connection reader;
|
|
reap;
|
|
connection locker;
|
|
drop table t1;
|
|
|
|
#
|
|
# Bug#31479 Bad lock interaction if CREATE TABLE LIKE is killed
|
|
#
|
|
|
|
--disable_warnings
|
|
drop table if exists t1;
|
|
--enable_warnings
|
|
create table t1 (a int);
|
|
--echo connection: locker
|
|
connection locker;
|
|
lock tables t1 read;
|
|
--echo connection: writer
|
|
connection writer;
|
|
let $ID= `select connection_id()`;
|
|
send create table t2 like t1;
|
|
--echo connection: default
|
|
connection default;
|
|
let $show_type= open tables where in_use=2 and name_locked=1;
|
|
let $show_pattern= '%t1%2%1';
|
|
--source include/wait_show_pattern.inc
|
|
--echo kill query
|
|
disable_query_log;
|
|
eval kill query $ID;
|
|
enable_query_log;
|
|
connection writer;
|
|
--error ER_QUERY_INTERRUPTED
|
|
--reap
|
|
connection locker;
|
|
unlock tables;
|
|
connection default;
|
|
drop table t1;
|
|
|
|
#
|
|
# Bug#38691 segfault/abort in ``UPDATE ...JOIN'' while
|
|
# ``FLUSH TABLES WITH READ LOCK''
|
|
#
|
|
|
|
--connection default
|
|
CREATE TABLE t1 (
|
|
a int(11) unsigned default NULL,
|
|
b varchar(255) default NULL,
|
|
UNIQUE KEY a (a),
|
|
KEY b (b)
|
|
);
|
|
|
|
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
|
|
CREATE TABLE t2 SELECT * FROM t1;
|
|
CREATE TABLE t3 SELECT * FROM t1;
|
|
|
|
--echo # test altering of columns that multiupdate doesn't use
|
|
|
|
--echo # normal mode
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
--dec $i
|
|
|
|
--connection writer
|
|
send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a)
|
|
SET a = NULL WHERE t1.b <> t2.b;
|
|
|
|
--connection locker
|
|
ALTER TABLE t2 ADD COLUMN (c INT);
|
|
ALTER TABLE t2 DROP COLUMN c;
|
|
|
|
--connection writer
|
|
--reap
|
|
}
|
|
|
|
--echo # PS mode
|
|
|
|
--connection writer
|
|
PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a)
|
|
SET a = NULL WHERE t1.b <> t2.b';
|
|
|
|
let $i = 100;
|
|
while ($i) {
|
|
--dec $i
|
|
|
|
--connection writer
|
|
--send EXECUTE stmt
|
|
|
|
--connection locker
|
|
ALTER TABLE t2 ADD COLUMN (c INT);
|
|
ALTER TABLE t2 DROP COLUMN c;
|
|
|
|
--connection writer
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
|
|
|
|
--echo # test altering of columns that multiupdate uses
|
|
|
|
--echo # normal mode
|
|
|
|
--connection default
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
dec $i;
|
|
|
|
--connection locker
|
|
--error 0,ER_DUP_FIELDNAME
|
|
ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL;
|
|
UPDATE t2 SET a=b;
|
|
|
|
--connection writer
|
|
--send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b
|
|
|
|
--connection locker
|
|
--error 0,ER_CANT_DROP_FIELD_OR_KEY
|
|
ALTER TABLE t2 DROP COLUMN a;
|
|
|
|
--connection writer
|
|
--error 0,ER_BAD_FIELD_ERROR
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
|
|
--echo # PS mode
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
dec $i;
|
|
|
|
--connection locker
|
|
--error 0,ER_DUP_FIELDNAME
|
|
ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL;
|
|
UPDATE t2 SET a=b;
|
|
|
|
--connection writer
|
|
PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b';
|
|
--send EXECUTE stmt
|
|
|
|
--connection locker
|
|
--error 0,ER_CANT_DROP_FIELD_OR_KEY
|
|
ALTER TABLE t2 DROP COLUMN a;
|
|
|
|
--connection writer
|
|
--error 0,ER_BAD_FIELD_ERROR
|
|
--reap
|
|
|
|
}
|
|
--enable_query_log
|
|
--connection default
|
|
DROP TABLE t1, t2, t3;
|
|
|
|
|
|
#
|
|
# Bug#38499: flush tables and multitable table update with derived table cause
|
|
# crash
|
|
#
|
|
|
|
CREATE TABLE t1( a INT, b INT );
|
|
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4);
|
|
|
|
--echo # 1. test regular tables
|
|
--echo # 1.1. test altering of columns that multiupdate doesn't use
|
|
--echo # 1.1.1. normal mode
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
--dec $i
|
|
|
|
--connection writer
|
|
send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0;
|
|
|
|
--connection locker
|
|
ALTER TABLE t1 ADD COLUMN (c INT);
|
|
ALTER TABLE t1 DROP COLUMN c;
|
|
|
|
--connection writer
|
|
--reap
|
|
}
|
|
|
|
--echo # 1.1.2. PS mode
|
|
|
|
--connection writer
|
|
PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0';
|
|
|
|
let $i = 100;
|
|
while ($i) {
|
|
--dec $i
|
|
|
|
--connection writer
|
|
--send EXECUTE stmt
|
|
|
|
--connection locker
|
|
ALTER TABLE t1 ADD COLUMN (c INT);
|
|
ALTER TABLE t1 DROP COLUMN c;
|
|
|
|
--connection writer
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
|
|
--echo # 1.2. test altering of columns that multiupdate uses
|
|
--echo # 1.2.1. normal mode
|
|
|
|
--connection default
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
dec $i;
|
|
|
|
--connection locker
|
|
--error 0,ER_DUP_FIELDNAME
|
|
ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL;
|
|
UPDATE t1 SET a=b;
|
|
|
|
--connection writer
|
|
--send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0;
|
|
|
|
--connection locker
|
|
--error 0,ER_CANT_DROP_FIELD_OR_KEY
|
|
ALTER TABLE t1 DROP COLUMN a;
|
|
|
|
--connection writer
|
|
--error 0,ER_BAD_FIELD_ERROR # unknown column error
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
|
|
--echo # 1.2.2. PS mode
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
dec $i;
|
|
|
|
--connection locker
|
|
--error 0,ER_DUP_FIELDNAME
|
|
ALTER TABLE t1 ADD COLUMN a INT;
|
|
UPDATE t1 SET a=b;
|
|
|
|
--connection writer
|
|
PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0';
|
|
--send EXECUTE stmt
|
|
|
|
--connection locker
|
|
--error 0,ER_CANT_DROP_FIELD_OR_KEY
|
|
ALTER TABLE t1 DROP COLUMN a;
|
|
|
|
--connection writer
|
|
--error 0,ER_BAD_FIELD_ERROR # Unknown column 'a' in 'field list'
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
--connection default
|
|
ALTER TABLE t1 ADD COLUMN a INT;
|
|
|
|
--echo # 2. test UNIONs
|
|
--echo # 2.1. test altering of columns that multiupdate doesn't use
|
|
--echo # 2.1.1. normal mode
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
--dec $i
|
|
|
|
--connection writer
|
|
send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0;
|
|
|
|
--connection locker
|
|
ALTER TABLE t1 ADD COLUMN (c INT);
|
|
ALTER TABLE t1 DROP COLUMN c;
|
|
|
|
--connection writer
|
|
--reap
|
|
}
|
|
|
|
--echo # 2.1.2. PS mode
|
|
|
|
--connection writer
|
|
PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0';
|
|
|
|
let $i = 100;
|
|
while ($i) {
|
|
--dec $i
|
|
|
|
--connection writer
|
|
--send EXECUTE stmt
|
|
|
|
--connection locker
|
|
ALTER TABLE t1 ADD COLUMN (c INT);
|
|
ALTER TABLE t1 DROP COLUMN c;
|
|
|
|
--connection writer
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
|
|
--echo # 2.2. test altering of columns that multiupdate uses
|
|
--echo # 2.2.1. normal mode
|
|
|
|
--connection default
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
dec $i;
|
|
|
|
--connection locker
|
|
--error 0,ER_DUP_FIELDNAME
|
|
ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL;
|
|
UPDATE t1 SET a=b;
|
|
|
|
--connection writer
|
|
--send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0;
|
|
|
|
--connection locker
|
|
--error 0,ER_CANT_DROP_FIELD_OR_KEY
|
|
ALTER TABLE t1 DROP COLUMN a;
|
|
|
|
--connection writer
|
|
--error 0,ER_BAD_FIELD_ERROR # Unknown column 'a' in 'field list'
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
|
|
--echo # 2.2.2. PS mode
|
|
|
|
--disable_query_log
|
|
let $i = 100;
|
|
while ($i) {
|
|
dec $i;
|
|
|
|
--connection locker
|
|
--error 0,ER_DUP_FIELDNAME
|
|
ALTER TABLE t1 ADD COLUMN a INT;
|
|
UPDATE t1 SET a=b;
|
|
|
|
--connection writer
|
|
PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0';
|
|
--send EXECUTE stmt
|
|
|
|
--connection locker
|
|
--error 0,ER_CANT_DROP_FIELD_OR_KEY
|
|
ALTER TABLE t1 DROP COLUMN a;
|
|
|
|
--connection writer
|
|
--error 0,ER_BAD_FIELD_ERROR # Unknown column 'a' in 'field list'
|
|
--reap
|
|
}
|
|
--enable_query_log
|
|
--connection default
|
|
DROP TABLE t1;
|
|
|
|
|
|
# Close connections used in many subtests
|
|
--disconnect reader
|
|
--disconnect locker
|
|
--disconnect writer
|
|
|
|
#
|
|
# 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;
|
|
|
|
# End of 5.0 tests
|
|
|
|
# Wait till all disconnects are completed
|
|
--source include/wait_until_count_sessions.inc
|
|
|