You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2731 lines
64 KiB
2731 lines
64 KiB
drop table if exists t1,t2;
|
|
create table t1(n int);
|
|
insert into t1 values (1);
|
|
select get_lock("mysqltest_lock", 100);
|
|
get_lock("mysqltest_lock", 100)
|
|
1
|
|
update t1 set n = 2 and get_lock('mysqltest_lock', 100);
|
|
update low_priority t1 set n = 4;
|
|
select n from t1;
|
|
select release_lock("mysqltest_lock");
|
|
release_lock("mysqltest_lock")
|
|
1
|
|
select release_lock("mysqltest_lock");
|
|
release_lock("mysqltest_lock")
|
|
1
|
|
n
|
|
4
|
|
drop table t1;
|
|
create table t1(n int);
|
|
insert into t1 values (1);
|
|
select get_lock("mysqltest_lock", 100);
|
|
get_lock("mysqltest_lock", 100)
|
|
1
|
|
select n from t1 where get_lock('mysqltest_lock', 100);
|
|
update low_priority t1 set n = 4;
|
|
select n from t1;
|
|
n
|
|
1
|
|
select release_lock("mysqltest_lock");
|
|
release_lock("mysqltest_lock")
|
|
1
|
|
n
|
|
1
|
|
select release_lock("mysqltest_lock");
|
|
release_lock("mysqltest_lock")
|
|
1
|
|
drop table t1;
|
|
#
|
|
# Test locking in multi-update statements.
|
|
#
|
|
#
|
|
# Multi-update should not be blocked by THR_LOCK locks acquired
|
|
# on table which is not updated.
|
|
#
|
|
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);
|
|
connection locker2;
|
|
select get_lock("mysqltest_lock", 100);
|
|
get_lock("mysqltest_lock", 100)
|
|
1
|
|
connection locker;
|
|
# Sending:
|
|
select a from t1 where get_lock('mysqltest_lock', 100);
|
|
connection writer;
|
|
# Wait till above select gets blocked on a user lock.
|
|
update t1,t2 set c=a where b=d;
|
|
connection reader;
|
|
select c from t2;
|
|
c
|
|
2
|
|
connection locker2;
|
|
select release_lock("mysqltest_lock");
|
|
release_lock("mysqltest_lock")
|
|
1
|
|
connection locker;
|
|
# Reap select.
|
|
a
|
|
1
|
|
2
|
|
select release_lock("mysqltest_lock");
|
|
release_lock("mysqltest_lock")
|
|
1
|
|
#
|
|
# Indeed it should be blocked by THR_LOCK locks on table
|
|
# which is updated.
|
|
#
|
|
connection locker2;
|
|
select get_lock("mysqltest_lock", 100);
|
|
get_lock("mysqltest_lock", 100)
|
|
1
|
|
connection locker;
|
|
# Sending:
|
|
select c from t2 where get_lock('mysqltest_lock', 100);
|
|
connection writer;
|
|
# Wait till above select gets blocked on a user lock.
|
|
# Sending:
|
|
update t1,t2 set c=a where b=d;;
|
|
connection default;
|
|
# Wait till multi-update is blocked on THR_LOCK lock
|
|
connection locker2;
|
|
select release_lock("mysqltest_lock");
|
|
release_lock("mysqltest_lock")
|
|
1
|
|
connection locker;
|
|
# Reap select.
|
|
c
|
|
2
|
|
select release_lock("mysqltest_lock");
|
|
release_lock("mysqltest_lock")
|
|
1
|
|
connection writer;
|
|
# Reap multi-update.
|
|
#
|
|
# OTOH multi-update will be blocked by concurrent LOCK TABLES READ
|
|
# on any table in the join. This is because multi-update acquires
|
|
# SW metadata locks on all tables in the join which conflicts with
|
|
# SRO metadata lock acquired by LOCK TABLES READ.
|
|
#
|
|
connection locker;
|
|
lock table t1 read;
|
|
connection writer;
|
|
# Sending:
|
|
update t1,t2 set c=a where b=d;;
|
|
connection default;
|
|
# Wait till multi-update is blocked on THR_LOCK lock
|
|
connection locker;
|
|
unlock tables;
|
|
connection writer;
|
|
# Reap multi-update.
|
|
connection locker;
|
|
lock table t2 read;
|
|
connection writer;
|
|
# Sending:
|
|
update t1,t2 set c=a where b=d;;
|
|
connection default;
|
|
# Wait till multi-update is blocked on THR_LOCK lock
|
|
connection locker;
|
|
unlock tables;
|
|
connection writer;
|
|
# Reap multi-update.
|
|
#
|
|
# Still if multi-update is executed under LOCK TABLES
|
|
# it will be compatible with LOCK TABLES READ on the
|
|
# table from its join which is only read.
|
|
#
|
|
# Main difference here is that LOCK TABLES preannounces
|
|
# locks which will be requested by multi-update.
|
|
#
|
|
connection locker;
|
|
lock table t1 read;
|
|
connection writer;
|
|
lock tables t1 read, t2 write;
|
|
update t1,t2 set c=a where b=d;
|
|
unlock tables;
|
|
connection locker;
|
|
unlock tables;
|
|
connection default;
|
|
drop table t1;
|
|
drop table t2;
|
|
create table t1 (a int);
|
|
create table t2 (a int);
|
|
lock table t1 write, t2 write;
|
|
insert t1 select * from t2;
|
|
drop table t2;
|
|
unlock tables;
|
|
ERROR 42S02: Table 'test.t2' doesn't exist
|
|
drop table t1;
|
|
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;
|
|
insert t1 select * from t2;
|
|
drop table t2;
|
|
unlock tables;
|
|
ERROR 42S02: Table 'test.t2' doesn't exist
|
|
drop table t1;
|
|
End of 4.1 tests
|
|
create table t1(a int);
|
|
lock tables t1 write;
|
|
show columns from t1;
|
|
Field Type Null Key Default Extra
|
|
a int(11) YES NULL
|
|
unlock tables;
|
|
drop table t1;
|
|
USE mysql;
|
|
LOCK TABLES columns_priv WRITE, db WRITE, user WRITE;
|
|
FLUSH TABLES;
|
|
USE mysql;
|
|
SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
|
|
OPTIMIZE TABLES columns_priv, db, user;
|
|
Table Op Msg_type Msg_text
|
|
mysql.columns_priv optimize note Table does not support optimize, doing recreate + analyze instead
|
|
mysql.columns_priv optimize status OK
|
|
mysql.db optimize note Table does not support optimize, doing recreate + analyze instead
|
|
mysql.db optimize status OK
|
|
mysql.user optimize note Table does not support optimize, doing recreate + analyze instead
|
|
mysql.user optimize status OK
|
|
UNLOCK TABLES;
|
|
Select_priv
|
|
N
|
|
USE test;
|
|
use test;
|
|
CREATE TABLE t1 (c1 int);
|
|
LOCK TABLE t1 WRITE;
|
|
FLUSH TABLES WITH READ LOCK;
|
|
CREATE TABLE t2 (c1 int);
|
|
ERROR HY000: Table 't2' was not locked with LOCK TABLES
|
|
UNLOCK TABLES;
|
|
UNLOCK TABLES;
|
|
DROP TABLE t1;
|
|
CREATE TABLE t1 (c1 int);
|
|
LOCK TABLE t1 WRITE;
|
|
FLUSH TABLES WITH READ LOCK;
|
|
CREATE TABLE t2 AS SELECT * FROM t1;
|
|
ERROR HY000: Table 't2' was not locked with LOCK TABLES
|
|
UNLOCK TABLES;
|
|
UNLOCK TABLES;
|
|
DROP TABLE t1;
|
|
CREATE DATABASE mysqltest_1;
|
|
FLUSH TABLES WITH READ LOCK;
|
|
DROP DATABASE mysqltest_1;
|
|
DROP DATABASE mysqltest_1;
|
|
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
|
UNLOCK TABLES;
|
|
DROP DATABASE mysqltest_1;
|
|
ERROR HY000: Can't drop database 'mysqltest_1'; database doesn't exist
|
|
create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) engine=innodb;
|
|
lock tables t1 write;
|
|
alter table t1 auto_increment=0;
|
|
alter table t1 auto_increment=0;
|
|
unlock tables;
|
|
drop table t1;
|
|
create table t1 (a int);
|
|
create table t2 like t1;
|
|
# con1
|
|
lock tables t1 write;
|
|
# con2
|
|
flush tables with read lock;
|
|
# con5
|
|
# global read lock is taken
|
|
# con3
|
|
select * from t2 for update;
|
|
# waiting for release of read lock
|
|
# con4
|
|
# would hang and later cause a deadlock
|
|
flush tables t2;
|
|
# clean up
|
|
unlock tables;
|
|
unlock tables;
|
|
a
|
|
drop table t1,t2;
|
|
#
|
|
# Lightweight version:
|
|
# Ensure that the wait for a GRL is done before opening tables.
|
|
#
|
|
create table t1 (a int);
|
|
create table t2 like t1;
|
|
#
|
|
# UPDATE
|
|
#
|
|
# default
|
|
flush tables with read lock;
|
|
# con1
|
|
update t2 set a = 1;
|
|
# default
|
|
# statement is waiting for release of read lock
|
|
# con2
|
|
flush table t2;
|
|
# default
|
|
unlock tables;
|
|
# con1
|
|
#
|
|
# LOCK TABLES .. WRITE
|
|
#
|
|
# default
|
|
flush tables with read lock;
|
|
# con1
|
|
lock tables t2 write;
|
|
# default
|
|
# statement is waiting for release of read lock
|
|
# con2
|
|
flush table t2;
|
|
# default
|
|
unlock tables;
|
|
# con1
|
|
unlock tables;
|
|
drop table t1,t2;
|
|
End of 5.0 tests
|
|
create table t1 (i int);
|
|
insert into t1 values (1);
|
|
select get_lock('mysqltest_lock', 100);
|
|
get_lock('mysqltest_lock', 100)
|
|
1
|
|
select * from t1 where get_lock('mysqltest_lock', 100);
|
|
update t1 set i= 10;
|
|
select * from t1;
|
|
kill query ID;
|
|
i
|
|
1
|
|
ERROR 70100: Query execution was interrupted
|
|
select release_lock('mysqltest_lock');
|
|
release_lock('mysqltest_lock')
|
|
1
|
|
i
|
|
1
|
|
select release_lock('mysqltest_lock');
|
|
release_lock('mysqltest_lock')
|
|
1
|
|
drop table t1;
|
|
drop table if exists t1;
|
|
create table t1 (a int) ENGINE=MEMORY;
|
|
--> client 2
|
|
handler t1 open;
|
|
ERROR HY000: Table storage engine for 't1' doesn't have this option
|
|
--> client 1
|
|
drop table t1;
|
|
drop table if exists t1;
|
|
create table t1 (i int);
|
|
connection: default
|
|
lock tables t1 write;
|
|
connection: flush
|
|
flush tables with read lock;;
|
|
connection: default
|
|
alter table t1 add column j int;
|
|
connection: insert
|
|
insert into t1 values (1,2);;
|
|
connection: default
|
|
unlock tables;
|
|
connection: flush
|
|
select * from t1;
|
|
i j
|
|
unlock tables;
|
|
select * from t1;
|
|
i j
|
|
1 2
|
|
drop table t1;
|
|
drop table if exists t1;
|
|
create table t1 (i int);
|
|
connection: default
|
|
lock tables t1 write;
|
|
connection: flush
|
|
flush tables with read lock;;
|
|
connection: default
|
|
flush tables;
|
|
unlock tables;
|
|
drop table t1;
|
|
drop table if exists t1,t2;
|
|
create table t1 (a int);
|
|
insert into t1 values (1);
|
|
select get_lock('mysqltest_lock', 100);
|
|
get_lock('mysqltest_lock', 100)
|
|
1
|
|
flush status;
|
|
select * from t1 where get_lock('mysqltest_lock', 100);
|
|
update t1 set a= 2;
|
|
select release_lock('mysqltest_lock');
|
|
release_lock('mysqltest_lock')
|
|
1
|
|
a
|
|
1
|
|
select release_lock('mysqltest_lock');
|
|
release_lock('mysqltest_lock')
|
|
1
|
|
drop table t1;
|
|
select @tlwa < @tlwb;
|
|
@tlwa < @tlwb
|
|
1
|
|
End of 5.1 tests
|
|
drop table if exists t1;
|
|
create table t1 (i int);
|
|
connection: default
|
|
lock tables t1 write;
|
|
connection: flush
|
|
flush tables with read lock;;
|
|
connection: default
|
|
flush tables;
|
|
drop table t1;
|
|
#
|
|
# Test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock".
|
|
#
|
|
drop table if exists t1;
|
|
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;
|
|
update t1 set c3=c3+1 where c2=3;
|
|
#
|
|
# Switching to connection 'con46272'.
|
|
# The below ALTER TABLE statement should wait till transaction
|
|
# in connection 'default' is complete and then succeed.
|
|
# It should not deadlock or fail with ER_LOCK_DEADLOCK error.
|
|
# Sending:
|
|
alter table t1 add column c4 int;;
|
|
#
|
|
# Switching to connection 'default'.
|
|
# Wait until the above ALTER TABLE gets blocked because this
|
|
# connection holds SW metadata lock on table to be altered.
|
|
# The below statement should succeed. It should not
|
|
# deadlock or end with ER_LOCK_DEADLOCK error.
|
|
update t1 set c3=c3+1 where c2=4;
|
|
# Unblock ALTER TABLE by committing transaction.
|
|
commit;
|
|
#
|
|
# Switching to connection 'con46272'.
|
|
# Reaping ALTER TABLE.
|
|
#
|
|
# Switching to connection 'default'.
|
|
drop table t1;
|
|
#
|
|
# Bug#47249 assert in MDL_global_lock::is_lock_type_compatible
|
|
#
|
|
DROP TABLE IF EXISTS t1;
|
|
DROP VIEW IF EXISTS v1;
|
|
#
|
|
# Test 1: LOCK TABLES v1 WRITE, t1 READ;
|
|
#
|
|
# Thanks to the fact that we no longer allow DDL on tables
|
|
# which are locked for write implicitly, the exact scenario
|
|
# in which assert was failing is no longer repeatable.
|
|
CREATE TABLE t1 ( f1 integer );
|
|
CREATE VIEW v1 AS SELECT f1 FROM t1 ;
|
|
# Connection 2
|
|
LOCK TABLES v1 WRITE, t1 READ;
|
|
FLUSH TABLE t1;
|
|
# Connection 1
|
|
LOCK TABLES t1 WRITE;
|
|
FLUSH TABLE t1;
|
|
UNLOCK TABLES;
|
|
DROP TABLE t1;
|
|
DROP VIEW v1;
|
|
#
|
|
# Test 2: LOCK TABLES t1 WRITE, v1 READ;
|
|
#
|
|
CREATE TABLE t1 ( f1 integer );
|
|
CREATE VIEW v1 AS SELECT f1 FROM t1 ;
|
|
# Connection 2
|
|
LOCK TABLES t1 WRITE, v1 READ;
|
|
FLUSH TABLE t1;
|
|
# Connection 1
|
|
LOCK TABLES t1 WRITE;
|
|
FLUSH TABLE t1;
|
|
DROP TABLE t1;
|
|
DROP VIEW v1;
|
|
#
|
|
# Test for bug #50913 "Deadlock between open_and_lock_tables_derived
|
|
# and MDL". Also see additional coverage in mdl_sync.test.
|
|
#
|
|
drop table if exists t1;
|
|
drop view if exists v1;
|
|
create table t1 (i int);
|
|
create view v1 as select i from t1;
|
|
begin;
|
|
select * from t1;
|
|
i
|
|
# Switching to connection 'con50913'.
|
|
# Sending:
|
|
alter table t1 add column j int;
|
|
# Switching to connection 'default'.
|
|
# Wait until ALTER TABLE gets blocked.
|
|
# The below statement should try to acquire SW lock on 't1'
|
|
# and therefore should get ER_LOCK_DEADLOCK error. Before
|
|
# bug fix it acquired SR lock and hung on thr_lock.c lock.
|
|
delete a from t1 as a where i = 1;
|
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
|
# Unblock ALTER TABLE.
|
|
commit;
|
|
# Switching to connection 'con50913'.
|
|
# Reaping ALTER TABLE;
|
|
# Switching to connection 'default'.
|
|
begin;
|
|
select * from v1;
|
|
i
|
|
# Switching to connection 'con50913'.
|
|
# Sending:
|
|
alter table t1 drop column j;
|
|
# Switching to connection 'default'.
|
|
# Wait until ALTER TABLE gets blocked.
|
|
# The below statement should try to acquire SW lock on 't1'
|
|
# and therefore should get ER_LOCK_DEADLOCK error. Before
|
|
# bug fix it acquired SR lock and hung on thr_lock.c lock.
|
|
insert into v1 values (1);
|
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
|
# Unblock ALTER TABLE.
|
|
commit;
|
|
# Switching to connection 'con50913'.
|
|
# Reaping ALTER TABLE;
|
|
# Switching to connection 'default'.
|
|
drop view v1;
|
|
drop table t1;
|
|
#
|
|
# Bug#45225 Locking: hang if drop table with no timeout
|
|
#
|
|
# These tests also provide function coverage for the
|
|
# lock_wait_timeout server variable.
|
|
#
|
|
DROP TABLE IF EXISTS t1;
|
|
CREATE TABLE t1 (id int);
|
|
SET SESSION lock_wait_timeout= 1;
|
|
#
|
|
# Test 1: acquire exclusive lock
|
|
#
|
|
# Connection default
|
|
START TRANSACTION;
|
|
INSERT INTO t1 VALUES (1);
|
|
# Connection 2
|
|
DROP TABLE t1;
|
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|
# Connection default
|
|
COMMIT;
|
|
#
|
|
# Test 2: upgrade shared lock
|
|
#
|
|
# Connection default
|
|
START TRANSACTION;
|
|
SELECT * FROM t1;
|
|
id
|
|
1
|
|
# Connection 2
|
|
ALTER TABLE t1 RENAME TO t2;
|
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|
# Connection default
|
|
COMMIT;
|
|
#
|
|
# Test 3: acquire shared lock
|
|
#
|
|
# Connection default
|
|
LOCK TABLE t1 WRITE;
|
|
# Connection 2
|
|
INSERT INTO t1(id) VALUES (2);
|
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|
# Connection default
|
|
UNLOCK TABLES;
|
|
#
|
|
# Test 4: table level locks
|
|
#
|
|
# Connection default
|
|
LOCK TABLE t1 READ;
|
|
# Connection 2
|
|
INSERT INTO t1(id) VALUES(4);
|
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|
# Connection default
|
|
UNLOCK TABLES;
|
|
#
|
|
# Test 5: Waiting on Table Definition Cache (TDC)
|
|
#
|
|
# Connection default
|
|
LOCK TABLE t1 READ;
|
|
# Connection con3
|
|
# Sending:
|
|
FLUSH TABLES;
|
|
# Connection con2
|
|
SELECT * FROM t1;
|
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|
# Connection default
|
|
UNLOCK TABLES;
|
|
# Connection con3
|
|
# Reaping: FLUSH TABLES
|
|
#
|
|
# Test 6: Timeouts in I_S queries
|
|
#
|
|
# Connection default
|
|
CREATE TABLE t2 (id INT);
|
|
LOCK TABLE t2 WRITE;
|
|
# Connection con3
|
|
# Sending:
|
|
DROP TABLE t1, t2;
|
|
# Connection con2
|
|
SET SESSION information_schema_stats_expiry=0;
|
|
SELECT table_name, table_rows, table_comment FROM information_schema.tables
|
|
WHERE table_schema= 'test' AND table_name= 't1';
|
|
TABLE_NAME TABLE_ROWS TABLE_COMMENT
|
|
t1 0 Lock wait timeout exceeded; try restarting transaction
|
|
Warnings:
|
|
Warning 1205 Lock wait timeout exceeded; try restarting transaction
|
|
SET SESSION information_schema_stats_expiry=default;
|
|
# Connection default
|
|
UNLOCK TABLES;
|
|
# Connection con3
|
|
# Reaping: DROP TABLE t1, t2
|
|
# Connection default
|
|
# Cleanup
|
|
#
|
|
# Test for bug #51134 "Crash in MDL_lock::destroy on a concurrent
|
|
# DDL workload".
|
|
#
|
|
drop tables if exists t1, t2, t3;
|
|
create table t3 (i int);
|
|
# Switching to connection 'con1'
|
|
# Lock 't3' so upcoming RENAME is blocked.
|
|
lock table t3 read;
|
|
# Switching to connection 'con2'
|
|
# Remember ID for this connection.
|
|
# Start statement which will try to acquire two instances
|
|
# of X metadata lock on the same object.
|
|
# Sending:
|
|
rename tables t1 to t2, t2 to t3;;
|
|
# Switching to connection 'default'
|
|
# Wait until RENAME TABLE is blocked on table 't3'.
|
|
# Kill RENAME TABLE.
|
|
kill query ID;
|
|
# Switching to connection 'con2'
|
|
# RENAME TABLE should be aborted but should not crash.
|
|
ERROR 70100: Query execution was interrupted
|
|
# Switching to connection 'con1'
|
|
unlock tables;
|
|
# Switching to connection 'default'
|
|
drop table t3;
|
|
#
|
|
# Test for the bug where upgradable metadata locks was acquired
|
|
# even if the table to altered was temporary.
|
|
# Bug found while working on the related bug #51240.
|
|
#
|
|
DROP TABLE IF EXISTS t1;
|
|
CREATE TABLE t1 (id INT);
|
|
LOCK TABLE t1 WRITE;
|
|
# Connection con1
|
|
CREATE TEMPORARY TABLE t1 (id INT);
|
|
ALTER TABLE t1 ADD COLUMN j INT;
|
|
# Connection default
|
|
UNLOCK TABLES;
|
|
DROP TABLE t1;
|
|
#
|
|
# Test coverage for LOCK TABLES ... READ/WRITE
|
|
#
|
|
# Of course this functionality is well-covered by tests all
|
|
# around the test suite. Still it is nice to have formal
|
|
# coverage for LOCK TABLES in one place.
|
|
#
|
|
# We are going to check behavior for both InnoDB and MyISAM
|
|
# tables.
|
|
CREATE TABLE t1 (i INT) ENGINE=MyISAM;
|
|
CREATE TABLE t2 (i INT) ENGINE=InnoDB;
|
|
INSERT INTO t1 VALUES (1);
|
|
INSERT INTO t2 VALUES (1);
|
|
CREATE VIEW v1 AS SELECT * FROM t1;
|
|
CREATE VIEW v2 AS SELECT * FROM t2;
|
|
CREATE TABLE t3 (j INT);
|
|
CREATE TABLE t4 (j INT);
|
|
CREATE VIEW v3 AS SELECT * FROM t3 WHERE (SELECT COUNT(*) FROM t1);
|
|
CREATE VIEW v4 AS SELECT * FROM t4 WHERE (SELECT COUNT(*) FROM t2);
|
|
CREATE TABLE t5 (k INT);
|
|
CREATE TABLE t6 (k INT);
|
|
CREATE TRIGGER bi_t5 BEFORE INSERT ON t5 FOR EACH ROW SET @a:= (SELECT COUNT(*) FROM t1);
|
|
CREATE TRIGGER bi_t6 BEFORE INSERT ON t6 FOR EACH ROW SET @a:= (SELECT COUNT(*) FROM t2);
|
|
CREATE TABLE t7 (z INT);
|
|
CREATE TABLE t8 (z INT);
|
|
CREATE TRIGGER bi_t7 BEFORE INSERT ON t7 FOR EACH ROW INSERT INTO t1 VALUES (1);
|
|
CREATE TRIGGER bi_t8 BEFORE INSERT ON t8 FOR EACH ROW INSERT INTO t2 VALUES (1);
|
|
#
|
|
# 1) LOCK TABLES READ explicitly locking table
|
|
#
|
|
# 1.a) Allows concurrent reads
|
|
LOCK TABLE t1 READ, t2 READ;
|
|
connect con1, localhost, root;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
#
|
|
# 1.b) Is allowed concurrently to reads
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t1, t2;;
|
|
connect con2, localhost, root;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# LOCK TABLES should not be blocked.
|
|
LOCK TABLES t1 READ, t2 READ;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
#
|
|
# 1.c) Blocks concurrent modifications to table
|
|
connection default;
|
|
LOCK TABLE t1 READ, t2 READ;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
connection con2;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
# Unblock INSERTs
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap INSERT
|
|
connection con2;
|
|
# Reap INSERT
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 1.d) Is blocked by concurrent table modifications
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t1 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
#
|
|
# The below part of test also covers scenario in which bug #42147
|
|
# "Concurrent DML and LOCK TABLE ... READ for InnoDB table cause
|
|
# warnings in errlog" occurred.
|
|
#
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t2 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 1.e) LOCK TABLES READ which explicitly locks table is not blocked
|
|
# by concurrent transactions which read table.
|
|
BEGIN;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
connection con1;
|
|
LOCK TABLES t1 READ;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
COMMIT;
|
|
BEGIN;
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection con1;
|
|
LOCK TABLES t2 READ;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
COMMIT;
|
|
#
|
|
# 1.f) LOCK TABLES READ which explicitly locks table is blocked
|
|
# by concurrent transactions which modify table.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES READ
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
INSERT INTO t2 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES READ
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 1.g) LOCK TABLES READ which explicitly locks table is compatible
|
|
# with itself.
|
|
LOCK TABLES t1 READ, t2 READ;
|
|
connection con1;
|
|
LOCK TABLES t1 READ, t2 READ;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
#
|
|
# 1.h) LOCK TABLES READ which explicitly locks table is not compatible
|
|
# with LOCK TABLE WRITE.
|
|
LOCK TABLES t1 READ;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t2 READ;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t1 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked
|
|
# Unblock LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked
|
|
# Unblock LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
#
|
|
# 2) LOCK TABLES WRITE explicitly locking table
|
|
#
|
|
# 2.a) Doesn't allow concurrent reads
|
|
connection default;
|
|
LOCK TABLE t1 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
SELECT * FROM t1;;
|
|
connection default;
|
|
# Wait until SELECT gets blocked
|
|
# Unblock SELECT
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping SELECT
|
|
i
|
|
1
|
|
connection default;
|
|
LOCK TABLE t2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
SELECT * FROM t2;;
|
|
connection default;
|
|
# Wait until SELECT gets blocked
|
|
# Unblock SELECT
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping SELECT
|
|
i
|
|
1
|
|
connection default;
|
|
#
|
|
# 2.b) Is not allowed concurrently to reads
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t1;;
|
|
connection con2;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLE WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t2;;
|
|
connection con2;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLE WRITE
|
|
UNLOCK TABLES;
|
|
#
|
|
# 2.c) Blocks concurrent modifications to table
|
|
connection default;
|
|
LOCK TABLE t1 WRITE, t2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
connection con2;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
# Unblock INSERTs
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap INSERT
|
|
connection con2;
|
|
# Reap INSERT
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 2.d) Is blocked by concurrent table modifications
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 2.e) LOCK TABLES WRITE which explicitly locks table is blocked
|
|
# by concurrent transactions which read table.
|
|
BEGIN;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
#
|
|
# 2.f) LOCK TABLES WRITE which explicitly locks table is blocked
|
|
# by concurrent transactions which modify table.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
INSERT INTO t2 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 2.g) LOCK TABLES WRITE which explicitly locks table is not compatible
|
|
# with itself.
|
|
LOCK TABLES t1 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
#
|
|
# 3) LOCK TABLES which locks table for read through view.
|
|
# Case of main table in mergeable view.
|
|
#
|
|
# 3.a) Allows concurrent reads
|
|
connection default;
|
|
LOCK TABLE v1 READ, v2 READ;
|
|
connection con1;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
#
|
|
# 3.b) Is allowed concurrently to reads
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t1, t2;;
|
|
connection con2;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# LOCK TABLES should not be blocked.
|
|
LOCK TABLES v1 READ, v2 READ;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
#
|
|
# 3.c) Blocks concurrent modifications to table
|
|
connection default;
|
|
LOCK TABLE v1 READ, v2 READ;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
connection con2;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
# Unblock INSERTs
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap INSERT
|
|
connection con2;
|
|
# Reap INSERT
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 3.d) Is blocked by concurrent table modifications
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES v1 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES v2 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 3.e) LOCK TABLES which locks table for read through view is not blocked
|
|
# by concurrent transactions which read table.
|
|
BEGIN;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
connection con1;
|
|
LOCK TABLES v1 READ;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
COMMIT;
|
|
BEGIN;
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection con1;
|
|
LOCK TABLES v2 READ;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
COMMIT;
|
|
#
|
|
# 3.f) LOCK TABLES which locks table for read through view is blocked
|
|
# by concurrent transactions which modify table.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v1 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES READ
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
INSERT INTO t2 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v2 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES READ
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 3.g) LOCK TABLES READ which locks table for read through view is
|
|
# compatible with explicit LOCK TABLES READ on the same table.
|
|
LOCK TABLES t1 READ, t2 READ;
|
|
connection con1;
|
|
LOCK TABLES v1 READ, v2 READ;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
#
|
|
# 3.h) LOCK TABLES READ which locks table for read through view is
|
|
# not compatible with explicit LOCK TABLES WRITE on the same table.
|
|
LOCK TABLES v1 READ;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES v2 READ;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t1 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v1 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked
|
|
# Unblock LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v2 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLES READ is blocked
|
|
# Unblock LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES READ
|
|
UNLOCK TABLES;
|
|
#
|
|
# 4) LOCK TABLES which locks table for read through mergeable view.
|
|
# Case of table not from the main join. Such table will be locked
|
|
# for read even though view is locked for write.
|
|
# 4.a) Allows concurrent reads
|
|
connection default;
|
|
LOCK TABLES v3 WRITE, v4 WRITE;
|
|
connection con1;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
#
|
|
# 4.b) Is allowed concurrently to reads
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t1, t2;;
|
|
connection con2;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# LOCK TABLES should not be blocked.
|
|
LOCK TABLES v3 WRITE, v4 WRITE;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
#
|
|
# 4.c) Blocks concurrent modifications to table
|
|
connection default;
|
|
LOCK TABLES v3 WRITE, v4 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
connection con2;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
# Unblock INSERTs
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap INSERT
|
|
connection con2;
|
|
# Reap INSERT
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 4.d) Is blocked by concurrent table modifications
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES v3 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES v4 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 4.e) LOCK TABLES which locks table for read through view is not blocked
|
|
# by concurrent transactions which read table.
|
|
BEGIN;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
connection con1;
|
|
LOCK TABLES v3 WRITE;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
COMMIT;
|
|
BEGIN;
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection con1;
|
|
LOCK TABLES v4 WRITE;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
COMMIT;
|
|
#
|
|
# 4.f) LOCK TABLES which locks table for read through view is blocked
|
|
# by concurrent transactions which modify table.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v3 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
INSERT INTO t2 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v4 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 4.g) LOCK TABLES which locks table for read through view is
|
|
# compatible with explicit LOCK TABLES READ on the same table.
|
|
LOCK TABLES t1 READ, t2 READ;
|
|
connection con1;
|
|
LOCK TABLES v3 WRITE, v4 WRITE;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
#
|
|
# 4.h) LOCK TABLES which locks table for read through view is
|
|
# not compatible with explicit LOCK TABLES WRITE on the same table.
|
|
LOCK TABLES v3 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES v4 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t1 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v3 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked
|
|
# Unblock LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v4 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES
|
|
UNLOCK TABLES;
|
|
#
|
|
# 5) LOCK TABLES which locks tables for write through view
|
|
#
|
|
# 5.a) Doesn't allow concurrent reads
|
|
connection default;
|
|
LOCK TABLE v1 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
SELECT * FROM t1;;
|
|
connection default;
|
|
# Wait until SELECT gets blocked
|
|
# Unblock SELECT
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping SELECT
|
|
i
|
|
1
|
|
connection default;
|
|
LOCK TABLE v2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
SELECT * FROM t2;;
|
|
connection default;
|
|
# Wait until SELECT gets blocked
|
|
# Unblock SELECT
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping SELECT
|
|
i
|
|
1
|
|
connection default;
|
|
#
|
|
# 5.b) Is not allowed concurrently to reads
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t1;;
|
|
connection con2;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES v1 WRITE;;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLE WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t2;;
|
|
connection con2;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES v2 WRITE;;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLE WRITE
|
|
UNLOCK TABLES;
|
|
#
|
|
# 5.c) Blocks concurrent modifications to table
|
|
connection default;
|
|
LOCK TABLE v1 WRITE, v2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
connection con2;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
# Unblock INSERTs
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap INSERT
|
|
connection con2;
|
|
# Reap INSERT
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 5.d) Is blocked by concurrent table modifications
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES v1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES v2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 5.e) LOCK TABLES which locks table for write through view is blocked
|
|
# by concurrent transactions which read table.
|
|
BEGIN;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
#
|
|
# 5.f) LOCK TABLES which locks table for write through view is blocked
|
|
# by concurrent transactions which modify table.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
INSERT INTO t2 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES v2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 5.g) LOCK TABLES which locks table for write through view is not
|
|
# compatible with LOCK TABLE WRITE.
|
|
LOCK TABLES v1 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES v2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
#
|
|
# 6) LOCK TABLES which locks table for read through trigger.
|
|
#
|
|
# 6.a) Allows concurrent reads
|
|
connection default;
|
|
LOCK TABLES t5 WRITE, t6 WRITE;
|
|
connection con1;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
#
|
|
# 6.b) Is allowed concurrently to reads
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t1, t2;;
|
|
connection con2;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# LOCK TABLES should not be blocked.
|
|
LOCK TABLES v3 WRITE, t6 WRITE;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
#
|
|
# 6.c) Blocks concurrent modifications to table
|
|
connection default;
|
|
LOCK TABLES t5 WRITE, t6 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
connection con2;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
# Unblock INSERTs
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap INSERT
|
|
connection con2;
|
|
# Reap INSERT
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 6.d) Is blocked by concurrent table modifications
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t5 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t6 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 6.e) LOCK TABLES which locks table for read through trigger is not
|
|
# blocked by concurrent transactions which read table.
|
|
BEGIN;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
connection con1;
|
|
LOCK TABLES t5 WRITE;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
COMMIT;
|
|
BEGIN;
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection con1;
|
|
LOCK TABLES t6 WRITE;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
COMMIT;
|
|
#
|
|
# 6.f) LOCK TABLES which locks table for read through trigger is
|
|
# blocked by concurrent transactions which modify table.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t5 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
INSERT INTO t2 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t6 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 6.g) LOCK TABLES which locks table for read through trigger is
|
|
# compatible with explicit LOCK TABLES READ on the same table.
|
|
LOCK TABLES t1 READ, t2 READ;
|
|
connection con1;
|
|
LOCK TABLES t5 WRITE, t6 WRITE;
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
#
|
|
# 6.h) LOCK TABLES which locks table for read through trigger is
|
|
# not compatible with explicit LOCK TABLES WRITE on the same table.
|
|
LOCK TABLES t5 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t6 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t1 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t5 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES is blocked
|
|
# Unblock LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t2 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t6 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES
|
|
UNLOCK TABLES;
|
|
#
|
|
# 7) LOCK TABLES which locks tables for write through trigger
|
|
#
|
|
# 7.a) Doesn't allow concurrent reads
|
|
connection default;
|
|
LOCK TABLE t7 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
SELECT * FROM t1;;
|
|
connection default;
|
|
# Wait until SELECT gets blocked
|
|
# Unblock SELECT
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping SELECT
|
|
i
|
|
1
|
|
connection default;
|
|
LOCK TABLE t8 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
SELECT * FROM t2;;
|
|
connection default;
|
|
# Wait until SELECT gets blocked
|
|
# Unblock SELECT
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping SELECT
|
|
i
|
|
1
|
|
connection default;
|
|
#
|
|
# 7.b) Is not allowed concurrently to reads
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t1;;
|
|
connection con2;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t7 WRITE;;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLE WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Start read by sending SELECT:
|
|
SELECT GET_LOCK('mysqltest_lock', 100) FROM t2;;
|
|
connection con2;
|
|
# Wait until SELECT gets read lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t8 WRITE;;
|
|
connection default;
|
|
UNLOCK TABLES;
|
|
# Unblock SELECT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping SELECT
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLE WRITE
|
|
UNLOCK TABLES;
|
|
#
|
|
# 7.c) Blocks concurrent modifications to table
|
|
connection default;
|
|
LOCK TABLE t7 WRITE, t8 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
connection con2;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT gets blocked
|
|
# Unblock INSERTs
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap INSERT
|
|
connection con2;
|
|
# Reap INSERT
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 7.d) Is blocked by concurrent table modifications
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t7 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
SELECT GET_LOCK('mysqltest_lock', 100);
|
|
GET_LOCK('mysqltest_lock', 100)
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (GET_LOCK('mysqltest_lock', 100));;
|
|
connection con2;
|
|
# Wait until INSERT gets SW MDL lock and starts waiting for user lock
|
|
# Sending:
|
|
LOCK TABLES t8 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due to INSERT
|
|
# Unblock INSERT.
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con1;
|
|
# Reaping INSERT
|
|
SELECT RELEASE_LOCK('mysqltest_lock');
|
|
RELEASE_LOCK('mysqltest_lock')
|
|
1
|
|
connection con2;
|
|
# Reaping LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 7.e) LOCK TABLES which locks table for write through trigger is blocked
|
|
# by concurrent transactions which read table.
|
|
BEGIN;
|
|
SELECT * FROM t1;
|
|
i
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t7 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
SELECT * FROM t2;
|
|
i
|
|
1
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t8 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
#
|
|
# 7.f) LOCK TABLES which locks table for write through trigger is blocked
|
|
# by concurrent transactions which modify table.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t7 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
BEGIN;
|
|
INSERT INTO t2 VALUES (1);
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t8 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked due concurrent transaction
|
|
# Unblock LOCK TABLES WRITE
|
|
COMMIT;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
# Revert effects from INSERTs
|
|
DELETE FROM t1 LIMIT 1;
|
|
DELETE FROM t2 LIMIT 1;
|
|
#
|
|
# 7.g) LOCK TABLES which locks table for write through trigger is not
|
|
# compatible with LOCK TABLE WRITE.
|
|
LOCK TABLES t7 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t1 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection default;
|
|
LOCK TABLES t8 WRITE;
|
|
connection con1;
|
|
# Sending:
|
|
LOCK TABLES t2 WRITE;;
|
|
connection default;
|
|
# Wait until LOCK TABLES WRITE is blocked
|
|
# Unblock LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reap LOCK TABLES WRITE
|
|
UNLOCK TABLES;
|
|
disconnect con1;
|
|
disconnect con2;
|
|
connection default;
|
|
DROP VIEW v1, v2, v3, v4;
|
|
DROP TABLES t1, t2, t3, t4, t5, t6, t7, t8;
|
|
#
|
|
# Test coverage for LOCK TABLES ... READ LOCAL
|
|
#
|
|
SET @old_concurrent_insert= @@global.concurrent_insert;
|
|
SET @@global.concurrent_insert= 1;
|
|
CREATE TABLE t1 (i INT) ENGINE=MyISAM;
|
|
CREATE TABLE t2 (i INT) ENGINE=InnoDB;
|
|
CREATE VIEW v1 AS SELECT * FROM t1;
|
|
CREATE VIEW v2 AS (SELECT * FROM t1) UNION (SELECT * FROM t1);
|
|
CREATE VIEW v3 AS SELECT * FROM t2;
|
|
#
|
|
# 1) READ LOCAL is fully supported for MyISAM.
|
|
# Concurrent inserts are allowed.
|
|
#
|
|
LOCK TABLE t1 READ LOCAL;
|
|
connect con1, localhost, root;
|
|
INSERT INTO t1 VALUES (1);
|
|
#
|
|
# Concurrent updates are blocked.
|
|
#
|
|
# Sending:
|
|
UPDATE t1 SET i= 2;
|
|
connection default;
|
|
# Wait until UPDATE is blocked.
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping UPDATE.
|
|
#
|
|
# 2) READ LOCAL works even for mergeable views on
|
|
# top of MyISAM tables.
|
|
#
|
|
connection default;
|
|
LOCK TABLE v1 READ LOCAL;
|
|
connection con1;
|
|
INSERT INTO v1 VALUES (1);
|
|
INSERT INTO t1 VALUES (3);
|
|
# Concurrent updates are blocked.
|
|
# Sending:
|
|
UPDATE t1 SET i= 2;
|
|
connection default;
|
|
# Wait until UPDATE is blocked.
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping UPDATE.
|
|
#
|
|
# 3) READ LOCAL doesn't work for non-mergeable views on
|
|
# top of MyISAM tables.
|
|
#
|
|
connection default;
|
|
LOCK TABLE v2 READ LOCAL;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT is blocked.
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping INSERT.
|
|
connection default;
|
|
LOCK TABLE v2 READ LOCAL;
|
|
connection con1;
|
|
# Sending:
|
|
UPDATE t1 SET i= 2;;
|
|
connection default;
|
|
# Wait until UPDATE is blocked.
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping UPDATE.
|
|
#
|
|
# 4) READ LOCAL locks are upgraded to simple READ locks
|
|
# for InnoDB tables. So they block both concurrent inserts
|
|
# and updates.
|
|
#
|
|
connection default;
|
|
LOCK TABLE t2 READ LOCAL;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT is blocked.
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping INSERT.
|
|
connection default;
|
|
LOCK TABLE t2 READ LOCAL;
|
|
connection con1;
|
|
# Sending:
|
|
UPDATE t2 SET i= 2;;
|
|
connection default;
|
|
# Wait until UPDATE is blocked.
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping UPDATE.
|
|
#
|
|
# 5) For mergeable views on top of InnoDB tables READ LOCAL locks are
|
|
# upgraded to simple READ locks as well.
|
|
#
|
|
connection default;
|
|
LOCK TABLE v3 READ LOCAL;
|
|
connection con1;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);
|
|
connection default;
|
|
# Wait until INSERT is blocked.
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping INSERT.
|
|
connection default;
|
|
LOCK TABLE v3 READ LOCAL;
|
|
connection con1;
|
|
# Sending:
|
|
UPDATE t2 SET i= 2;;
|
|
connection default;
|
|
# Wait until UPDATE is blocked.
|
|
UNLOCK TABLES;
|
|
connection con1;
|
|
# Reaping UPDATE.
|
|
connection default;
|
|
disconnect con1;
|
|
DROP VIEW v1, v2, v3;
|
|
DROP TABLES t1, t2;
|
|
SET @@global.concurrent_insert= @old_concurrent_insert;
|
|
#
|
|
# Test coverage for interaction between LOCK TABLE ... READ and
|
|
# concurrent DML which uses LOW_PRIORITY and HIGH_PRIORITY clauses/
|
|
# concurrent DML which is executed in @@low_priority_updates=1 mode.
|
|
#
|
|
# We will use MyISAM to avoid row-locks.
|
|
CREATE TABLE t1 (i INT) ENGINE=MyISAM;
|
|
CREATE VIEW v1 AS SELECT * FROM t1;
|
|
CREATE TABLE t2 (j INT);
|
|
CREATE TRIGGER t2_ai AFTER INSERT ON t2 FOR EACH ROW
|
|
INSERT LOW_PRIORITY INTO t1 VALUES (2);
|
|
CREATE TABLE t3 (k INT);
|
|
CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW
|
|
INSERT INTO t1 VALUES (2);
|
|
CREATE TABLE tm (i INT) ENGINE=MERGE UNION=(t1);
|
|
#
|
|
# 1) Let us check that DML operations with LOW_PRIORITY clauses have
|
|
# lower priority than pending LOCK TABLE ... READ, thus can't starve
|
|
# it out.
|
|
#
|
|
# Acquire SW lock on the table, to create pending LOCK TABLE ... READ.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (1);
|
|
connect blocker, localhost, root;
|
|
# Sending:
|
|
LOCK TABLE t1 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLE READ gets blocked
|
|
connect con_insert, localhost, root;
|
|
# INSERT HIGH_PRIORITY should not get blocked
|
|
INSERT HIGH_PRIORITY INTO t1 VALUES (1);
|
|
# Sending:
|
|
INSERT LOW_PRIORITY INTO t1 VALUES (1);;
|
|
connection default;
|
|
# Check that INSERT is blocked
|
|
connect con_replace, localhost, root;
|
|
# Sending:
|
|
REPLACE LOW_PRIORITY INTO t1 VALUES (1);;
|
|
connection default;
|
|
# Check that REPLACE is blocked
|
|
connect con_update, localhost, root;
|
|
# Sending:
|
|
UPDATE LOW_PRIORITY t1 SET i= 1;;
|
|
connection default;
|
|
# Check that UPDATE is blocked
|
|
connect con_update_multi, localhost, root;
|
|
# Sending:
|
|
UPDATE LOW_PRIORITY t1 AS a, t1 AS b SET a.i= 1;;
|
|
connection default;
|
|
# Check that multi-UPDATE is blocked
|
|
connect con_delete, localhost, root;
|
|
# Sending:
|
|
DELETE LOW_PRIORITY FROM t1 LIMIT 1;;
|
|
connection default;
|
|
# Check that DELETE is blocked
|
|
connect con_delete_multi, localhost, root;
|
|
# Sending:
|
|
DELETE LOW_PRIORITY FROM a USING t1 AS a, t1 AS b;;
|
|
connection default;
|
|
# Check that multi-DELETE is blocked
|
|
connect con_load, localhost, root;
|
|
# Sending:
|
|
LOAD DATA LOW_PRIORITY INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE t1 (@dummy,i);;
|
|
connection default;
|
|
# Check that LOAD DATA is blocked
|
|
#
|
|
# This should work even for views.
|
|
#
|
|
connect con_view, localhost, root;
|
|
# Sending:
|
|
DELETE LOW_PRIORITY FROM v1;;
|
|
connection default;
|
|
# Check that DELETE is blocked
|
|
#
|
|
# And when LOW_PRIORITY clause is used in trigger.
|
|
#
|
|
connect con_trigger, localhost, root;
|
|
# Sending:
|
|
INSERT INTO t2 VALUES (1);;
|
|
connection default;
|
|
# Check that INSERT in trigger is blocked
|
|
#
|
|
# And for MERGE tables
|
|
#
|
|
connect con_merge, localhost, root;
|
|
# Sending:
|
|
DELETE LOW_PRIORITY FROM tm LIMIT 1;;
|
|
connection default;
|
|
# Check that DELETE from MERGE table is blocked
|
|
# Unblock LOCK TABLE .. READ
|
|
COMMIT;
|
|
connection blocker;
|
|
# Reaping LOCK TABLE .. READ
|
|
UNLOCK TABLES;
|
|
# Reap all DML statements.
|
|
connection con_insert;
|
|
connection con_replace;
|
|
connection con_update;
|
|
connection con_update_multi;
|
|
connection con_delete;
|
|
connection con_delete_multi;
|
|
connection con_load;
|
|
connection con_view;
|
|
connection con_trigger;
|
|
connection con_merge;
|
|
connection default;
|
|
#
|
|
# 2) Let us check that DML operations have lower priority than pending
|
|
# LOCK TABLE ... READ when @@low_priority_updates mode is on.
|
|
#
|
|
# Acquire SW lock on the table, to create pending LOCK TABLE ... READ.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (0);
|
|
connection blocker;
|
|
# Sending:
|
|
LOCK TABLE t1 READ;;
|
|
connection default;
|
|
# Wait until LOCK TABLE READ gets blocked
|
|
connection con_insert;
|
|
SET @@session.low_priority_updates= 1;
|
|
# INSERT HIGH_PRIORITY still should not get blocked
|
|
INSERT HIGH_PRIORITY INTO t1 VALUES (1);
|
|
# Sending:
|
|
INSERT INTO t1 VALUES (1);;
|
|
connection default;
|
|
# Check that INSERT is blocked
|
|
connection con_replace;
|
|
SET @@session.low_priority_updates= 1;
|
|
# Sending:
|
|
REPLACE INTO t1 VALUES (1);;
|
|
connection default;
|
|
# Check that REPLACE is blocked
|
|
connection con_update;
|
|
SET @@session.low_priority_updates= 1;
|
|
# Sending:
|
|
UPDATE t1 SET i= 1;;
|
|
connection default;
|
|
# Check that UPDATE is blocked
|
|
connection con_update_multi;
|
|
SET @@session.low_priority_updates= 1;
|
|
# Sending:
|
|
UPDATE t1 AS a, t1 AS b SET a.i= 1;;
|
|
connection default;
|
|
# Check that multi-UPDATE is blocked
|
|
connection con_delete;
|
|
SET @@session.low_priority_updates= 1;
|
|
# Sending:
|
|
DELETE FROM t1 LIMIT 1;;
|
|
connection default;
|
|
# Check that DELETE is blocked
|
|
connection con_delete_multi;
|
|
SET @@session.low_priority_updates= 1;
|
|
# Sending:
|
|
DELETE FROM a USING t1 AS a, t1 AS b;;
|
|
connection default;
|
|
# Check that multi-DELETE is blocked
|
|
connection con_load;
|
|
SET @@session.low_priority_updates= 1;
|
|
# Sending:
|
|
LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE t1 (@dummy,i);;
|
|
connection default;
|
|
# Check that LOAD DATA is blocked
|
|
connection con_view;
|
|
SET @@session.low_priority_updates= 1;
|
|
# Sending:
|
|
DELETE FROM v1;;
|
|
connection default;
|
|
# Check that DELETE is blocked
|
|
#
|
|
# And when table used in trigger.
|
|
#
|
|
connection con_trigger;
|
|
SET @@session.low_priority_updates= 1;
|
|
# Sending:
|
|
INSERT INTO t3 VALUES (1);;
|
|
connection default;
|
|
# Check that INSERT in trigger is blocked
|
|
#
|
|
# And for MERGE tables
|
|
#
|
|
connection con_merge;
|
|
SET @@session.low_priority_updates= 1;
|
|
# Sending:
|
|
DELETE FROM tm LIMIT 1;;
|
|
connection default;
|
|
# Check that DELETE from MERGE table is blocked
|
|
# Unblock LOCK TABLE .. READ
|
|
COMMIT;
|
|
connection blocker;
|
|
# Reaping LOCK TABLE .. READ
|
|
UNLOCK TABLES;
|
|
# Reap all DML statements.
|
|
connection con_insert;
|
|
connection con_replace;
|
|
connection con_update;
|
|
connection con_update_multi;
|
|
connection con_delete;
|
|
connection con_delete_multi;
|
|
connection con_load;
|
|
connection con_view;
|
|
connection con_trigger;
|
|
connection con_merge;
|
|
connection default;
|
|
disconnect blocker;
|
|
disconnect con_insert;
|
|
disconnect con_replace;
|
|
disconnect con_update;
|
|
disconnect con_update_multi;
|
|
disconnect con_delete;
|
|
disconnect con_delete_multi;
|
|
disconnect con_load;
|
|
disconnect con_view;
|
|
disconnect con_trigger;
|
|
disconnect con_merge;
|
|
DROP VIEW v1;
|
|
DROP TABLES tm, t2, t3, t1;
|
|
#
|
|
# Test for bug #11764618 "DEADLOCK WHEN DDL UNDER LOCK TABLES
|
|
# WRITE, READ + PREPARE".
|
|
#
|
|
connect con1,localhost,root,,test,,;
|
|
connect con2,localhost,root,,test,,;
|
|
connect con3,localhost,root,,test,,;
|
|
connection default;
|
|
create table t1(i int);
|
|
create table t2(i int);
|
|
create table t3(i int);
|
|
create table t4(i int);
|
|
lock tables t1 write, t3 read;
|
|
connection con1;
|
|
begin;
|
|
select count(*) from t4;
|
|
count(*)
|
|
0
|
|
# Sending:
|
|
insert into t3 values (1);;
|
|
connection con2;
|
|
# Wait until 'con1' acquires SR metadata lock on 't4'
|
|
# and blocks on 't3'. Before WL#6671 waiting has happened
|
|
# on THR_LOCK lock which led to deadlock.
|
|
# Sending:
|
|
rename table t2 to t0, t4 to t2, t0 to t4;;
|
|
connection con3;
|
|
# Wait until RENAME acquires X metadata lock on 't2'
|
|
# and blocks on 't4'.
|
|
# Sending:
|
|
prepare stmt1 from 'select * from t1, t2';;
|
|
connection default;
|
|
# Wait until PREPARE acquires S metadata lock on 't1'
|
|
# and blocks on 't2'.
|
|
# This ALTER TABLE upgrades SNRW lock on t1 to X lock.
|
|
# In the past this caused deadlock.
|
|
alter table t1 add column j int;
|
|
unlock tables;
|
|
connection con1;
|
|
# Reap INSERT
|
|
commit;
|
|
connection con2;
|
|
# Reap RENAME
|
|
connection con3;
|
|
# Reap PREPARE
|
|
connection default;
|
|
disconnect con1;
|
|
disconnect con2;
|
|
disconnect con3;
|
|
drop tables t1, t2, t3, t4;
|
|
|