Commit d665e79c authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-7660 - MySQL WL#6671 "Improve scalability by not using thr_lock.c locks

            for InnoDB tables"

Don't use thr_lock.c locks for InnoDB tables. Below is list of changes that
were needed to implement this:
- HANDLER OPEN acquireis MDL_SHARED_READ instead of MDL_SHARED
- HANDLER READ calls external_lock() even if SE is not going to be locked by
  THR_LOCK
- InnoDB lock wait timeouts are now honored which are much shorter by default
  than server lock wait timeouts (1 year vs 50 seconds)
- with @@autocommit= 1 LOCK TABLES disables autocommit implicitely, though
  user still sees @@autocommt= 1
- the above starts implicit transaction
- transactions started by LOCK TABLES are now rolled back on disconnect
  (previously everything was committed due to autocommit)
- transactions started by LOCK TABLES are now rolled back by ROLLBACK
  (previously everything was committed due to autocommit)
- it is now impossible to change BINLOG_FORMAT under LOCK TABLES (at least
  to statement) due to running transaction
- LOCK TABLES WRITE is additionally handled by MDL
- ...in contrast LOCK TABLES READ protection against DML is pure InnoDB
- combining transactional and non-transactional tables under LOCK TABLES
  may cause rolled back changes in transactional table and "committed"
  changes in non-transactional table
- user may disable innodb_table_locks, which will cause LOCK TABLES to be
  noop basically

Removed tests for BUG#45143 and BUG#55930 which cover InnoDB + THR_LOCK. To
operate properly these tests require code flow to go through THR_LOCK debug
sync points, which is not the case after this patch. These tests are removed
by WL#6671 as well. An alternative is to port them to different storage engine.
parent e2d69126
......@@ -205,14 +205,6 @@ INSERT INTO global_suppressions VALUES
("==[0-9]*== Warning: invalid file descriptor -1 in syscall write()"),
("==[0-9]*== Warning: invalid file descriptor -1 in syscall read()"),
/*
BUG#42147 - Concurrent DML and LOCK TABLE ... READ for InnoDB
table cause warnings in errlog
Note: This is a temporary suppression until Bug#42147 can be
fixed properly. See bug page for more information.
*/
("Found lock of type 6 that is write and read locked"),
/*
Transient network failures that cause warnings on reconnect.
BUG#47743 and BUG#47983.
......
......@@ -361,9 +361,6 @@ sub mtr_report_stats ($) {
/Slave: Can't DROP 'c7'.* 1091/ or
/Slave: Key column 'c6'.* 1072/ or
# Warnings generated until bug#42147 is properly resolved
/Found lock of type 6 that is write and read locked/ or
# rpl_idempotency.test produces warnings for the slave.
($testname eq 'rpl.rpl_idempotency' and
(/Slave: Can\'t find record in \'t1\' error.* 1032/ or
......
......@@ -95,8 +95,6 @@ LOCK TABLES t1 READ;
SELECT release_lock('bug42147_lock');
release_lock('bug42147_lock')
1
connection default;
connection con2;
UNLOCK TABLES;
connection default;
disconnect con2;
......
......@@ -338,6 +338,7 @@ Success: 'load data infile '../../std_data/rpl_loaddata.dat' into table t2 (@a,
# 2.8 REPLACE with a subquery.
#
# Same is true for this statement as well.
# Suppress warnings for REPLACE ... SELECT
connection default;
Success: 'replace into t2 select i+5 from t1' doesn't allow concurrent inserts into 't1'.
connection default;
......@@ -704,87 +705,6 @@ disconnect con1;
disconnect con2;
set @@global.concurrent_insert= @old_concurrent_insert;
#
# Test for bug #45143 "All connections hang on concurrent ALTER TABLE".
#
# Concurrent execution of statements which required weak write lock
# (TL_WRITE_ALLOW_WRITE) on several instances of the same table and
# statements which tried to acquire stronger write lock (TL_WRITE,
# TL_WRITE_ALLOW_READ) on this table might have led to deadlock.
drop table if exists t1;
drop view if exists v1;
# Create auxiliary connections used through the test.
connect con_bug45143_1,localhost,root,,test,,;
connect con_bug45143_3,localhost,root,,test,,;
connect con_bug45143_2,localhost,root,,test,,;
connection default;
# Reset DEBUG_SYNC facility before using it.
set debug_sync= 'RESET';
# Turn off logging so calls to locking subsystem performed
# for general_log table won't interfere with our test.
set @old_general_log = @@global.general_log;
set @@global.general_log= OFF;
create table t1 (i int) engine=InnoDB;
# We have to use view in order to make LOCK TABLES avoid
# acquiring SNRW metadata lock on table.
create view v1 as select * from t1;
insert into t1 values (1);
# Prepare user lock which will be used for resuming execution of
# the first statement after it acquires TL_WRITE_ALLOW_WRITE lock.
select get_lock("lock_bug45143_wait", 0);
get_lock("lock_bug45143_wait", 0)
1
connection con_bug45143_1;
# Sending:
insert into t1 values (get_lock("lock_bug45143_wait", 100));;
connection con_bug45143_2;
# Wait until the above INSERT takes TL_WRITE_ALLOW_WRITE lock on 't1'
# and then gets blocked on user lock 'lock_bug45143_wait'.
# Ensure that upcoming SELECT waits after acquiring TL_WRITE_ALLOW_WRITE
# lock for the first instance of 't1'.
set debug_sync='thr_multi_lock_after_thr_lock SIGNAL parked WAIT_FOR go';
# Sending:
select count(*) > 0 from t1 as a, t1 as b for update;;
connection con_bug45143_3;
# Wait until the above SELECT ... FOR UPDATE is blocked after
# acquiring lock for the the first instance of 't1'.
set debug_sync= 'now WAIT_FOR parked';
# Send LOCK TABLE statement which will try to get TL_WRITE lock on 't1':
lock table v1 write;;
connection default;
# Wait until this LOCK TABLES statement starts waiting for table lock.
# Allow SELECT ... FOR UPDATE to resume.
# Since it already has TL_WRITE_ALLOW_WRITE lock on the first instance
# of 't1' it should be able to get lock on the second instance without
# waiting, even although there is another thread which has such lock
# on this table and also there is a thread waiting for a TL_WRITE on it.
set debug_sync= 'now SIGNAL go';
connection con_bug45143_2;
# Reap SELECT ... FOR UPDATE
count(*) > 0
1
connection default;
# Resume execution of the INSERT statement.
select release_lock("lock_bug45143_wait");
release_lock("lock_bug45143_wait")
1
connection con_bug45143_1;
# Reap INSERT statement.
# In Statement and Mixed replication mode we get here "Unsafe
# for binlog" warnings. In row mode there are no warnings.
# Hide the discrepancy.
connection con_bug45143_3;
# Reap LOCK TABLES statement.
unlock tables;
connection default;
# Do clean-up.
disconnect con_bug45143_1;
disconnect con_bug45143_2;
disconnect con_bug45143_3;
set debug_sync= 'RESET';
set @@global.general_log= @old_general_log;
drop view v1;
drop table t1;
#
# Bug#50821 Deadlock between LOCK TABLES and ALTER TABLE
#
DROP TABLE IF EXISTS t1, t2;
......@@ -827,44 +747,6 @@ connection default;
DROP EVENT e2;
SET DEBUG_SYNC="RESET";
#
# Bug#55930 Assertion `thd->transaction.stmt.is_empty() ||
# thd->in_sub_stmt || (thd->state..
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INT) engine=InnoDB;
INSERT INTO t1 VALUES (1), (2);
connect con1, localhost, root;
connect con2, localhost, root;
connection con1;
SET SESSION lock_wait_timeout= 1;
SET DEBUG_SYNC= 'ha_admin_open_ltable SIGNAL opti_recreate WAIT_FOR opti_analyze';
# Sending:
OPTIMIZE TABLE t1;
connection con2;
SET DEBUG_SYNC= 'now WAIT_FOR opti_recreate';
SET DEBUG_SYNC= 'after_lock_tables_takes_lock SIGNAL thrlock WAIT_FOR release_thrlock';
# Sending:
INSERT INTO t1 VALUES (3);
connection default;
SET DEBUG_SYNC= 'now WAIT_FOR thrlock';
SET DEBUG_SYNC= 'now SIGNAL opti_analyze';
connection con1;
# Reaping: OPTIMIZE TABLE t1
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize error Lock wait timeout exceeded; try restarting transaction
test.t1 optimize status Operation failed
Warnings:
Error 1205 Lock wait timeout exceeded; try restarting transaction
SET DEBUG_SYNC= 'now SIGNAL release_thrlock';
disconnect con1;
connection con2;
# Reaping: INSERT INTO t1 VALUES (3)
disconnect con2;
connection default;
DROP TABLE t1;
SET DEBUG_SYNC= 'RESET';
#
# Bug#57130 crash in Item_field::print during SHOW CREATE TABLE or VIEW
#
DROP TABLE IF EXISTS t1;
......
......@@ -9,7 +9,6 @@ disconnect con1;
connection con2;
SELECT * FROM t1;
a
10
DROP TABLE t1;
connection default;
disconnect con2;
This diff is collapsed.
......@@ -64,29 +64,3 @@ disconnect con1;
connection default;
SET DEBUG_SYNC= 'RESET';
End of 5.1 tests
#
# Coverage test for non pruned ha_partition::store_lock()
#
CREATE TABLE t1 (a int) ENGINE = InnoDB;
CREATE TABLE t2 (a int PRIMARY KEY)
ENGINE = InnoDB PARTITION BY HASH (a) PARTITIONS 3;
HANDLER t1 OPEN;
connect con1, localhost, root,,;
LOCK TABLES t1 WRITE, t2 READ;
connection default;
SET DEBUG_SYNC="wait_for_lock SIGNAL locking";
INSERT INTO t2 VALUES (1), (2), (3);
connection con1;
SET DEBUG_SYNC="now WAIT_FOR locking";
ALTER TABLE t1 ADD COLUMN b int;
connection default;
ERROR HY000: Wait on a lock was aborted due to a pending exclusive lock
SELECT 1;
1
1
connection con1;
UNLOCK TABLES;
disconnect con1;
connection default;
SET DEBUG_SYNC = 'RESET';
DROP TABLE t1, t2;
......@@ -281,7 +281,7 @@ UNLOCK TABLES;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 2
HANDLER_COMMIT 3
HANDLER_READ_RND_NEXT 54
HANDLER_TMP_WRITE 75
HANDLER_WRITE 2
......@@ -440,7 +440,7 @@ UNLOCK TABLES;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 5
HANDLER_COMMIT 6
HANDLER_READ_FIRST 3
HANDLER_READ_NEXT 4
HANDLER_READ_RND_NEXT 108
......@@ -665,7 +665,7 @@ UNLOCK TABLES;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 5
HANDLER_COMMIT 6
HANDLER_DELETE 2
HANDLER_READ_FIRST 1
HANDLER_READ_KEY 3
......@@ -758,7 +758,7 @@ UNLOCK TABLES;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 2
HANDLER_COMMIT 3
HANDLER_READ_RND_NEXT 54
HANDLER_TMP_WRITE 75
HANDLER_WRITE 10
......@@ -953,7 +953,7 @@ UNLOCK TABLES;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 3
HANDLER_COMMIT 4
HANDLER_DELETE 1
HANDLER_READ_KEY 2
HANDLER_READ_RND 2
......@@ -1039,7 +1039,7 @@ UNLOCK TABLES;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 3
HANDLER_COMMIT 4
HANDLER_DELETE 2
HANDLER_READ_KEY 3
HANDLER_READ_NEXT 1
......
......@@ -6,48 +6,6 @@ DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT);
INSERT INTO t1 VALUES (1);
connect con1, localhost, root,,;
HANDLER t1 OPEN;
connection default;
LOCK TABLE t1 WRITE;
SET DEBUG_SYNC='mdl_upgrade_lock SIGNAL waiting';
TRUNCATE TABLE t1;
connect con2, localhost, root,,;
SET DEBUG_SYNC='now WAIT_FOR waiting';
KILL QUERY @id;
disconnect con2;
connection default;
ERROR 70100: Query execution was interrupted
UNLOCK TABLES;
connection con1;
# Release shared metadata lock by closing HANDLER.
HANDLER t1 CLOSE;
disconnect con1;
connection default;
DROP TABLE t1;
SET DEBUG_SYNC='RESET';
CREATE TABLE t1 (c1 INT);
INSERT INTO t1 VALUES (1);
connect con1, localhost, root,,;
HANDLER t1 OPEN;
connection default;
LOCK TABLE t1 WRITE;
SET DEBUG_SYNC='mdl_upgrade_lock SIGNAL waiting';
TRUNCATE TABLE t1;
connect con2, localhost, root,,;
SET DEBUG_SYNC='now WAIT_FOR waiting';
disconnect con2;
connection con1;
HANDLER t1 CLOSE;
disconnect con1;
connection default;
ERROR 42S02: Table 'test.t1' doesn't exist
UNLOCK TABLES;
DROP TABLE t1;
ERROR 42S02: Unknown table 'test.t1'
SET DEBUG_SYNC='RESET';
CREATE TABLE t1 (c1 INT);
INSERT INTO t1 VALUES (1);
connect con1, localhost, root,,;
START TRANSACTION;
INSERT INTO t1 VALUES (2);
connection default;
......
......@@ -545,7 +545,6 @@ optimize table t1;
connection default;
handler t1 read next;
c1
1
handler t1 close;
connection con2;
Table Op Msg_type Msg_text
......@@ -1296,19 +1295,27 @@ commit;
# an open HANDLER, ER_LOCK_DEADLOCK is reported.
#
create table t1 (a int, key a(a));
create table t2 like t1;
handler t1 open;
connection con1;
lock table t1 write, t2 write;
select get_lock('lock1', 10);
get_lock('lock1', 10)
1
connection default;
drop table t2;
select get_lock('lock1', 10);
connection con2;
# Waiting for 'drop table t2' to get blocked...
# Waiting for 'select get_lock('lock1', 10)' to get blocked...
connection con1;
drop table t1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
unlock tables;
select release_lock('lock1');
release_lock('lock1')
1
connection default;
get_lock('lock1', 10)
1
select release_lock('lock1');
release_lock('lock1')
1
# Demonstrate that there is no deadlock with FLUSH TABLE,
# even though it is waiting for the other table to go away
create table t2 like t1;
......@@ -1347,6 +1354,10 @@ handler t1 read a next;
a
1
# Unblock 'lock tables t1 write'.
select * from t1;
a
1
2
commit;
connection con1;
# Reap 'lock tables t1 write'.
......@@ -1516,10 +1527,6 @@ handler t1 read a last;
a b
7 7
commit;
connection con1;
# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
lock table t1 write;
unlock tables;
connection default;
handler t1 read a prev;
a b
......
......@@ -1054,24 +1054,24 @@ commit;
--echo # an open HANDLER, ER_LOCK_DEADLOCK is reported.
--echo #
create table t1 (a int, key a(a));
create table t2 like t1;
handler t1 open;
connection con1;
lock table t1 write, t2 write;
select get_lock('lock1', 10);
connection default;
send drop table t2;
send select get_lock('lock1', 10);
connection con2;
--echo # Waiting for 'drop table t2' to get blocked...
--echo # Waiting for 'select get_lock('lock1', 10)' to get blocked...
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t2';
where state='User lock' and
info='select get_lock(\'lock1\', 10)';
--source include/wait_condition.inc
connection con1;
--error ER_LOCK_DEADLOCK
drop table t1;
unlock tables;
select release_lock('lock1');
connection default;
reap;
select release_lock('lock1');
--echo # Demonstrate that there is no deadlock with FLUSH TABLE,
--echo # even though it is waiting for the other table to go away
......@@ -1118,6 +1118,7 @@ connection default;
handler t1 read a next;
--echo # Unblock 'lock tables t1 write'.
select * from t1; # Release MDL_SHARED_READ held by HANDLER
commit;
connection con1;
......@@ -1132,7 +1133,7 @@ connection con1;
--echo # Waiting for 'handler t1 read a next' to get blocked...
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for table level lock" and
where state = "Waiting for table metadata lock" and
info = "handler t1 read a next";
--source include/wait_condition.inc
......@@ -1259,10 +1260,6 @@ handler t1 read a last;
insert into t1 (a, b) values (7, 7);
handler t1 read a last;
commit;
connection con1;
--echo # Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
lock table t1 write;
unlock tables;
connection default;
handler t1 read a prev;
handler t1 close;
......
......@@ -545,7 +545,6 @@ optimize table t1;
connection default;
handler t1 read next;
c1
1
handler t1 close;
connection con2;
Table Op Msg_type Msg_text
......@@ -1296,19 +1295,27 @@ commit;
# an open HANDLER, ER_LOCK_DEADLOCK is reported.
#
create table t1 (a int, key a(a));
create table t2 like t1;
handler t1 open;
connection con1;
lock table t1 write, t2 write;
select get_lock('lock1', 10);
get_lock('lock1', 10)
1
connection default;
drop table t2;
select get_lock('lock1', 10);
connection con2;
# Waiting for 'drop table t2' to get blocked...
# Waiting for 'select get_lock('lock1', 10)' to get blocked...
connection con1;
drop table t1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
unlock tables;
select release_lock('lock1');
release_lock('lock1')
1
connection default;
get_lock('lock1', 10)
1
select release_lock('lock1');
release_lock('lock1')
1
# Demonstrate that there is no deadlock with FLUSH TABLE,
# even though it is waiting for the other table to go away
create table t2 like t1;
......@@ -1347,6 +1354,10 @@ handler t1 read a next;
a
1
# Unblock 'lock tables t1 write'.
select * from t1;
a
1
2
commit;
connection con1;
# Reap 'lock tables t1 write'.
......@@ -1516,10 +1527,6 @@ handler t1 read a last;
a b
7 7
commit;
connection con1;
# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
lock table t1 write;
unlock tables;
connection default;
handler t1 read a prev;
a b
......
......@@ -1299,19 +1299,27 @@ commit;
# an open HANDLER, ER_LOCK_DEADLOCK is reported.
#
create table t1 (a int, key a(a));
create table t2 like t1;
handler t1 open;
connection con1;
lock table t1 write, t2 write;
select get_lock('lock1', 10);
get_lock('lock1', 10)
1
connection default;
drop table t2;
select get_lock('lock1', 10);
connection con2;
# Waiting for 'drop table t2' to get blocked...
# Waiting for 'select get_lock('lock1', 10)' to get blocked...
connection con1;
drop table t1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
unlock tables;
select release_lock('lock1');
release_lock('lock1')
1
connection default;
get_lock('lock1', 10)
1
select release_lock('lock1');
release_lock('lock1')
1
# Demonstrate that there is no deadlock with FLUSH TABLE,
# even though it is waiting for the other table to go away
create table t2 like t1;
......@@ -1350,6 +1358,10 @@ handler t1 read a next;
a
1
# Unblock 'lock tables t1 write'.
select * from t1;
a
1
2
commit;
connection con1;
# Reap 'lock tables t1 write'.
......@@ -1519,10 +1531,6 @@ handler t1 read a last;
a b
7 7
commit;
connection con1;
# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
lock table t1 write;
unlock tables;
connection default;
handler t1 read a prev;
a b
......
......@@ -272,24 +272,6 @@ handler t1 read a next;
ERROR 42S02: Unknown table 't1' in HANDLER
connect con1,localhost,root,,;
connect con2,localhost,root,,;
connection default;
drop table if exists t1;
# First test case which is supposed trigger the execution
# path on which problem was discovered.
create table t1 (a int not null);
insert into t1 values (1);
handler t1 open;
connection con1;
lock table t1 write;
alter table t1 engine=csv;
connection con2;
connection default;
handler t1 read a next;
ERROR HY000: Storage engine CSV of the table `test`.`t1` doesn't have this option
handler t1 close;
connection con1;
unlock tables;
drop table t1;
# Now test case which was reported originally but which no longer
# triggers execution path which has caused the problem.
connection default;
......
......@@ -298,32 +298,6 @@ handler t1 read a next;
connect(con1,localhost,root,,);
connect(con2,localhost,root,,);
connection default;
--disable_warnings
drop table if exists t1;
--enable_warnings
--echo # First test case which is supposed trigger the execution
--echo # path on which problem was discovered.
create table t1 (a int not null);
insert into t1 values (1);
handler t1 open;
connection con1;
lock table t1 write;
send alter table t1 engine=csv;
connection con2;
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for table metadata lock" and
info = "alter table t1 engine=csv";
--source include/wait_condition.inc
connection default;
--error ER_ILLEGAL_HA
handler t1 read a next;
handler t1 close;
connection con1;
--reap
unlock tables;
drop table t1;
--echo # Now test case which was reported originally but which no longer
--echo # triggers execution path which has caused the problem.
connection default;
......
......@@ -545,7 +545,6 @@ optimize table t1;
connection default;
handler t1 read next;
c1
1
handler t1 close;
connection con2;
Table Op Msg_type Msg_text
......@@ -1296,19 +1295,27 @@ commit;
# an open HANDLER, ER_LOCK_DEADLOCK is reported.
#
create table t1 (a int, key a(a));
create table t2 like t1;
handler t1 open;
connection con1;
lock table t1 write, t2 write;
select get_lock('lock1', 10);
get_lock('lock1', 10)
1
connection default;
drop table t2;
select get_lock('lock1', 10);
connection con2;
# Waiting for 'drop table t2' to get blocked...
# Waiting for 'select get_lock('lock1', 10)' to get blocked...
connection con1;
drop table t1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
unlock tables;
select release_lock('lock1');
release_lock('lock1')
1
connection default;
get_lock('lock1', 10)
1
select release_lock('lock1');
release_lock('lock1')
1
# Demonstrate that there is no deadlock with FLUSH TABLE,
# even though it is waiting for the other table to go away
create table t2 like t1;
......@@ -1347,6 +1354,10 @@ handler t1 read a next;
a
1
# Unblock 'lock tables t1 write'.
select * from t1;
a
1
2
commit;
connection con1;
# Reap 'lock tables t1 write'.
......@@ -1516,10 +1527,6 @@ handler t1 read a last;
a b
7 7
commit;
connection con1;
# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
lock table t1 write;
unlock tables;
connection default;
handler t1 read a prev;
a b
......
......@@ -410,6 +410,7 @@ LOCK TABLES t11 WRITE;
SET SESSION BINLOG_FORMAT=ROW;
INSERT INTO t11 VALUES('Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict');
SET SESSION BINLOG_FORMAT=STATEMENT;
ERROR HY000: Cannot modify @@session.binlog_format inside a transaction
INSERT INTO t11 VALUES('Careful With That Axe, Eugene');
UNLOCK TABLES;
SELECT * FROM t11;
......
......@@ -524,6 +524,7 @@ CREATE TABLE t11 (song VARCHAR(255));
LOCK TABLES t11 WRITE;
SET SESSION BINLOG_FORMAT=ROW;
INSERT INTO t11 VALUES('Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict');
--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
SET SESSION BINLOG_FORMAT=STATEMENT;
INSERT INTO t11 VALUES('Careful With That Axe, Eugene');
UNLOCK TABLES;
......
......@@ -150,14 +150,16 @@ let $wait_condition=
--source include/wait_condition.inc
LOCK TABLES t1 READ;
SELECT release_lock('bug42147_lock');
let $wait_condition=
SELECT COUNT(*) > 0 FROM information_schema.processlist
WHERE state = 'executing'
AND info = 'INSERT INTO t1 SELECT get_lock(\'bug42147_lock\', 60)';
--source include/wait_condition.inc
UNLOCK TABLES;
connection default;
--reap
connection con2;
UNLOCK TABLES;
connection default;
disconnect con2;
DROP TABLE t1;
......
......@@ -406,6 +406,12 @@ let $restore_table= t2;
--echo # 2.8 REPLACE with a subquery.
--echo #
--echo # Same is true for this statement as well.
--echo # Suppress warnings for REPLACE ... SELECT
--disable_query_log
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
--enable_query_log
let $statement= replace into t2 select i+5 from t1;
let $restore_table= t2;
--source include/check_no_concurrent_insert.inc
......@@ -872,116 +878,6 @@ disconnect con2;
set @@global.concurrent_insert= @old_concurrent_insert;
--echo #
--echo # Test for bug #45143 "All connections hang on concurrent ALTER TABLE".
--echo #
--echo # Concurrent execution of statements which required weak write lock
--echo # (TL_WRITE_ALLOW_WRITE) on several instances of the same table and
--echo # statements which tried to acquire stronger write lock (TL_WRITE,
--echo # TL_WRITE_ALLOW_READ) on this table might have led to deadlock.
#
# Suppress warnings for INSERTs that use get_lock().
#
disable_query_log;
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
enable_query_log;
--disable_warnings
drop table if exists t1;
drop view if exists v1;
--enable_warnings
--echo # Create auxiliary connections used through the test.
connect (con_bug45143_1,localhost,root,,test,,);
connect (con_bug45143_3,localhost,root,,test,,);
connect (con_bug45143_2,localhost,root,,test,,);
connection default;
--echo # Reset DEBUG_SYNC facility before using it.
set debug_sync= 'RESET';
--echo # Turn off logging so calls to locking subsystem performed
--echo # for general_log table won't interfere with our test.
set @old_general_log = @@global.general_log;
set @@global.general_log= OFF;
create table t1 (i int) engine=InnoDB;
--echo # We have to use view in order to make LOCK TABLES avoid
--echo # acquiring SNRW metadata lock on table.
create view v1 as select * from t1;
insert into t1 values (1);
--echo # Prepare user lock which will be used for resuming execution of
--echo # the first statement after it acquires TL_WRITE_ALLOW_WRITE lock.
select get_lock("lock_bug45143_wait", 0);
connection con_bug45143_1;
--echo # Sending:
--send insert into t1 values (get_lock("lock_bug45143_wait", 100));
connection con_bug45143_2;
--echo # Wait until the above INSERT takes TL_WRITE_ALLOW_WRITE lock on 't1'
--echo # and then gets blocked on user lock 'lock_bug45143_wait'.
let $wait_condition= select count(*)= 1 from information_schema.processlist
where state= 'User lock' and
info='insert into t1 values (get_lock("lock_bug45143_wait", 100))';
--source include/wait_condition.inc
--echo # Ensure that upcoming SELECT waits after acquiring TL_WRITE_ALLOW_WRITE
--echo # lock for the first instance of 't1'.
set debug_sync='thr_multi_lock_after_thr_lock SIGNAL parked WAIT_FOR go';
--echo # Sending:
--send select count(*) > 0 from t1 as a, t1 as b for update;
connection con_bug45143_3;
--echo # Wait until the above SELECT ... FOR UPDATE is blocked after
--echo # acquiring lock for the the first instance of 't1'.
set debug_sync= 'now WAIT_FOR parked';
--echo # Send LOCK TABLE statement which will try to get TL_WRITE lock on 't1':
--send lock table v1 write;
connection default;
--echo # Wait until this LOCK TABLES statement starts waiting for table lock.
let $wait_condition= select count(*)= 1 from information_schema.processlist
where state= 'Waiting for table level lock' and
info='lock table v1 write';
--source include/wait_condition.inc
--echo # Allow SELECT ... FOR UPDATE to resume.
--echo # Since it already has TL_WRITE_ALLOW_WRITE lock on the first instance
--echo # of 't1' it should be able to get lock on the second instance without
--echo # waiting, even although there is another thread which has such lock
--echo # on this table and also there is a thread waiting for a TL_WRITE on it.
set debug_sync= 'now SIGNAL go';
connection con_bug45143_2;
--echo # Reap SELECT ... FOR UPDATE
--reap
connection default;
--echo # Resume execution of the INSERT statement.
select release_lock("lock_bug45143_wait");
connection con_bug45143_1;
--echo # Reap INSERT statement.
--echo # In Statement and Mixed replication mode we get here "Unsafe
--echo # for binlog" warnings. In row mode there are no warnings.
--echo # Hide the discrepancy.
--disable_warnings
--reap
--enable_warnings
connection con_bug45143_3;
--echo # Reap LOCK TABLES statement.
--reap
unlock tables;
connection default;
--echo # Do clean-up.
disconnect con_bug45143_1;
disconnect con_bug45143_2;
disconnect con_bug45143_3;
set debug_sync= 'RESET';
set @@global.general_log= @old_general_log;
drop view v1;
drop table t1;
--echo #
--echo # Bug#50821 Deadlock between LOCK TABLES and ALTER TABLE
--echo #
......@@ -1050,55 +946,6 @@ DROP EVENT e2;
SET DEBUG_SYNC="RESET";
--echo #
--echo # Bug#55930 Assertion `thd->transaction.stmt.is_empty() ||
--echo # thd->in_sub_stmt || (thd->state..
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1(a INT) engine=InnoDB;
INSERT INTO t1 VALUES (1), (2);
connect (con1, localhost, root);
connect (con2, localhost, root);
connection con1;
SET SESSION lock_wait_timeout= 1;
SET DEBUG_SYNC= 'ha_admin_open_ltable SIGNAL opti_recreate WAIT_FOR opti_analyze';
--echo # Sending:
--send OPTIMIZE TABLE t1
connection con2;
SET DEBUG_SYNC= 'now WAIT_FOR opti_recreate';
SET DEBUG_SYNC= 'after_lock_tables_takes_lock SIGNAL thrlock WAIT_FOR release_thrlock';
--echo # Sending:
--send INSERT INTO t1 VALUES (3)
connection default;
SET DEBUG_SYNC= 'now WAIT_FOR thrlock';
SET DEBUG_SYNC= 'now SIGNAL opti_analyze';
connection con1;
--echo # Reaping: OPTIMIZE TABLE t1
--reap
SET DEBUG_SYNC= 'now SIGNAL release_thrlock';
disconnect con1;
--source include/wait_until_disconnected.inc
connection con2;
--echo # Reaping: INSERT INTO t1 VALUES (3)
--reap
disconnect con2;
--source include/wait_until_disconnected.inc
connection default;
DROP TABLE t1;
SET DEBUG_SYNC= 'RESET';
--echo #
--echo # Bug#57130 crash in Item_field::print during SHOW CREATE TABLE or VIEW
--echo #
......
......@@ -119,10 +119,6 @@ alter table t1 add index (not_exist);
--echo # lock.
--error ER_DUP_ENTRY
alter table t1 add primary key (c1);
--echo # Check that SNRW lock is compatible with S lock.
lock table t1 write;
insert into t1 values (1);
unlock tables;
--echo # Check that X lock is incompatible with S lock.
--echo # Sending:
--send rename table t1 to t2;
......@@ -172,35 +168,6 @@ connection mdl_con1;
alter table t1 drop column c2;
--echo #
connection default;
handler t1 open;
--echo #
connection mdl_con1;
--echo # Check that upgrade from SNRW to X is blocked by presence of S lock.
lock table t1 write;
--echo # Sending:
--send alter table t1 add column c2 int;
--echo #
connection mdl_con2;
--echo # Check that the above upgrade of SNRW to X in ALTER TABLE is blocked
--echo # because of S lock.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for table metadata lock" and
info = "alter table t1 add column c2 int";
--source include/wait_condition.inc
--echo #
connection default;
--echo # Unblock ALTER TABLE.
handler t1 close;
--echo #
connection mdl_con1;
--echo # Reaping ALTER TABLE.
--reap
--echo # Restore the original state of the things.
alter table t1 drop column c2;
unlock tables;
--echo #
connection default;
--echo #
--echo # 2) Acquire SH (shared high-priority) lock on the table.
--echo # We have to involve DEBUG_SYNC facility for this as usually
......@@ -797,8 +764,6 @@ lock table t1 write;
--echo #
connection mdl_con1;
--echo # Check that S and SH locks are compatible with it.
handler t1 open;
handler t1 close;
select column_name from information_schema.columns where
table_schema='test' and table_name='t1';
--echo # Check that SR lock is incompatible with SNRW lock.
......@@ -1293,8 +1258,6 @@ where state = "Waiting for table metadata lock" and
info = "lock table t1 write";
--source include/wait_condition.inc
--echo # Check that S and SH locks are compatible with pending SNRW
handler t1 open t;
handler t close;
select column_name from information_schema.columns where
table_schema='test' and table_name='t1';
--echo # Check that SR is incompatible with pending SNRW
......@@ -2162,190 +2125,6 @@ disconnect mdl_con3;
set debug_sync= 'RESET';
drop table t1, t2;
--echo #
--echo # Additional coverage for some scenarios in which not quite
--echo # correct use of S metadata locks by HANDLER statement might
--echo # have caused deadlocks.
--echo #
--disable_warnings
drop table if exists t1, t2;
--enable_warnings
connect(handler_con1,localhost,root,,);
connect(handler_con2,localhost,root,,);
connection default;
create table t1 (i int);
create table t2 (j int);
insert into t1 values (1);
--echo #
--echo # First, check scenario in which we upgrade SNRW lock to X lock
--echo # on a table while having HANDLER READ trying to acquire TL_READ
--echo # on the same table.
--echo #
handler t1 open;
--echo #
connection handler_con1;
lock table t1 write;
--echo # Upgrade SNRW to X lock.
--echo # Sending:
--send alter table t1 add column j int;
--echo #
connection handler_con2;
--echo # Wait until ALTER is blocked during upgrade.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for table metadata lock" and
info = "alter table t1 add column j int";
--source include/wait_condition.inc
--echo #
connection default;
--echo # The below statement should not cause deadlock.
--send handler t1 read first;
--echo #
connection handler_con1;
--echo # Reap ALTER TABLE.
--reap
unlock tables;
--echo #
connection default;
--echo # Reap HANDLER READ.
--reap
handler t1 close;
--echo #
--echo # Now, check scenario in which upgrade of SNRW lock to X lock
--echo # can be blocked by HANDLER which is open in connection currently
--echo # waiting to get table-lock owned by connection doing upgrade.
--echo #
handler t1 open;
--echo #
connection handler_con1;
lock table t1 write, t2 read;
--echo #
connection default;
--echo # Execute statement which will be blocked on table-level lock
--echo # owned by connection 'handler_con1'.
--echo # Sending:
--send insert into t2 values (1);
--echo #
connection handler_con1;
--echo # Wait until INSERT is blocked on table-level lock.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for table level lock" and
info = "insert into t2 values (1)";
--source include/wait_condition.inc
--echo # Sending 'alter table t1 drop column j'. It should not cause
--echo # deadlock.
send alter table t1 drop column j;
connection handler_con2;
--echo # Wait until ALTER is blocked during upgrade.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for table metadata lock" and
info = "alter table t1 drop column j";
--source include/wait_condition.inc
--echo #
connection default;
--echo # Reap INSERT.
--error ER_LOCK_ABORTED
--reap
handler t1 close;
--echo #
connection handler_con1;
--echo # Reaping 'alter table t1 drop column j'
--reap
unlock tables;
connection default;
--echo # Then, check the scenario in which upgrade of SNRW lock to X
--echo # lock is blocked by HANDLER which is open in connection currently
--echo # waiting to get SW lock on the same table.
--echo #
handler t1 open;
--echo #
connection handler_con1;
lock table t1 write;
--echo #
connection default;
--echo # The below insert should be blocked because active SNRW lock on 't1'.
--echo # Sending:
--send insert into t1 values (1);
--echo #
connection handler_con1;
--echo # Wait until INSERT is blocked because of SNRW lock.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for table metadata lock" and
info = "insert into t1 values (1)";
--source include/wait_condition.inc
--echo # The below ALTER TABLE will be blocked because of presence of HANDLER.
--echo # Sending:
--send alter table t1 add column j int;
--echo #
connection default;
--echo # INSERT should be chosen as victim for resolving deadlock.
--echo # Reaping INSERT.
--error ER_LOCK_DEADLOCK
--reap
--echo # Close HANDLER to unblock ALTER TABLE.
handler t1 close;
--echo #
connection handler_con1;
--echo # Reaping ALTER TABLE.
--reap
unlock tables;
--echo #
connection default;
--echo #
--echo # Finally, test in which upgrade of SNRW lock to X lock is blocked
--echo # by HANDLER which is open in connection currently waiting to get
--echo # SR lock on the table on which lock is upgraded.
--echo #
handler t1 open;
--echo #
connection handler_con1;
lock table t1 write, t2 write;
--echo #
connection default;
--echo # The below insert should be blocked because active SNRW lock on 't1'.
--echo # Sending:
--send insert into t2 values (1);
--echo #
connection handler_con1;
--echo # Wait until INSERT is blocked because of SNRW lock.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for table metadata lock" and
info = "insert into t2 values (1)";
--source include/wait_condition.inc
--echo # The below ALTER TABLE will be blocked because of presence of HANDLER.
--echo # Sending:
--send alter table t1 drop column j;
--echo #
connection default;
--echo # INSERT should be chosen as victim for resolving deadlock.
--echo # Reaping INSERT.
--error ER_LOCK_DEADLOCK
--reap
--echo # Close HANDLER to unblock ALTER TABLE.
handler t1 close;
--echo #
connection handler_con1;
--echo # Reaping ALTER TABLE.
--reap
unlock tables;
--echo #
connection default;
--echo # Clean-up.
disconnect handler_con1;
disconnect handler_con2;
drop tables t1, t2;
--echo #
--echo # Test coverage for basic deadlock detection in metadata
--echo # locking subsystem.
......
......@@ -82,43 +82,3 @@ connection default;
SET DEBUG_SYNC= 'RESET';
--echo End of 5.1 tests
--echo #
--echo # Coverage test for non pruned ha_partition::store_lock()
--echo #
CREATE TABLE t1 (a int) ENGINE = InnoDB;
CREATE TABLE t2 (a int PRIMARY KEY)
ENGINE = InnoDB PARTITION BY HASH (a) PARTITIONS 3;
HANDLER t1 OPEN;
connect (con1, localhost, root,,);
LOCK TABLES t1 WRITE, t2 READ;
connection default;
SET DEBUG_SYNC="wait_for_lock SIGNAL locking";
send INSERT INTO t2 VALUES (1), (2), (3);
connection con1;
SET DEBUG_SYNC="now WAIT_FOR locking";
send ALTER TABLE t1 ADD COLUMN b int;
connection default;
--error ER_LOCK_ABORTED
--reap
SELECT 1;
connection con1;
--reap
UNLOCK TABLES;
--disconnect con1
connection default;
SET DEBUG_SYNC = 'RESET';
DROP TABLE t1, t2;
......@@ -17,86 +17,6 @@ DROP TABLE IF EXISTS t1;
--echo # Bug#20667 - Truncate table fails for a write locked table
--echo #
########
# Attack wait_while_table_is_used(). Kill query while trying to
# upgrade MDL.
#
CREATE TABLE t1 (c1 INT);
INSERT INTO t1 VALUES (1);
#
# Acquire a shared metadata lock on table by opening HANDLER for it and wait.
# TRUNCATE shall block on this metadata lock.
# We can't use normal DML as such statements would also block LOCK TABLES.
#
--connect (con1, localhost, root,,)
HANDLER t1 OPEN;
#
# Get connection id of default connection.
# Lock the table and start TRUNCATE, which will block on MDL upgrade.
#
--connection default
let $ID= `SELECT @id := CONNECTION_ID()`;
LOCK TABLE t1 WRITE;
SET DEBUG_SYNC='mdl_upgrade_lock SIGNAL waiting';
send TRUNCATE TABLE t1;
#
# Get the default connection ID into a variable in an invisible statement.
# Kill the TRUNCATE query. This shall result in an error return
# from wait_while_table_is_used().
#
--connect (con2, localhost, root,,)
SET DEBUG_SYNC='now WAIT_FOR waiting';
let $invisible_assignment_in_select = `SELECT @id := $ID`;
KILL QUERY @id;
--disconnect con2
--connection default
--error ER_QUERY_INTERRUPTED
reap;
UNLOCK TABLES;
--connection con1
--echo # Release shared metadata lock by closing HANDLER.
HANDLER t1 CLOSE;
--disconnect con1
--connection default
DROP TABLE t1;
SET DEBUG_SYNC='RESET';
########
# Attack reopen_tables(). Remove form file.
#
CREATE TABLE t1 (c1 INT);
INSERT INTO t1 VALUES (1);
#
# Acquire a shared metadata lock on table by opening HANDLER for it and wait.
# TRUNCATE shall block on this metadata lock.
# We can't use normal DML as such statements would also block LOCK TABLES.
#
--connect (con1, localhost, root,,)
HANDLER t1 OPEN;
#
# Lock the table and start TRUNCATE, which will block on MDL upgrade.
#
--connection default
LOCK TABLE t1 WRITE;
SET DEBUG_SYNC='mdl_upgrade_lock SIGNAL waiting';
send TRUNCATE TABLE t1;
#
# Remove datafile.
# Commit to let TRUNCATE continue.
#
--connect (con2, localhost, root,,)
SET DEBUG_SYNC='now WAIT_FOR waiting';
--remove_file $MYSQLD_DATADIR/test/t1.frm
--disconnect con2
--connection con1
HANDLER t1 CLOSE;
--disconnect con1
--connection default
--error ER_NO_SUCH_TABLE
reap;
UNLOCK TABLES;
--error ER_BAD_TABLE_ERROR
DROP TABLE t1;
SET DEBUG_SYNC='RESET';
########
# Attack acquire_exclusive_locks(). Hold a global read lock.
# Non-LOCK TABLE case.
#
......
......@@ -2150,6 +2150,11 @@ Locked_tables_list::unlock_locked_tables(THD *thd)
request for metadata locks and TABLE_LIST elements.
*/
reset();
if (thd->variables.option_bits & OPTION_AUTOCOMMIT)
{
thd->variables.option_bits&= ~(OPTION_NOT_AUTOCOMMIT);
thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
}
}
......
......@@ -282,7 +282,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
back-off for such locks.
*/
tables->mdl_request.init(MDL_key::TABLE, tables->db, tables->table_name,
MDL_SHARED, MDL_TRANSACTION);
MDL_SHARED_READ, MDL_TRANSACTION);
mdl_savepoint= thd->mdl_context.mdl_savepoint();
/* for now HANDLER can be used only for real TABLES */
......@@ -750,11 +750,12 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
tables->table= table; // This is used by fix_fields
table->pos_in_table_list= tables;
if (handler->lock->lock_count > 0)
if (handler->lock->table_count > 0)
{
int lock_error;
handler->lock->locks[0]->type= handler->lock->locks[0]->org_type;
if (handler->lock->lock_count > 0)
handler->lock->locks[0]->type= handler->lock->locks[0]->org_type;
/* save open_tables state */
TABLE* backup_open_tables= thd->open_tables;
......
......@@ -4794,7 +4794,8 @@ mysql_execute_command(THD *thd)
if (lock_tables_precheck(thd, all_tables))
goto error;
thd->variables.option_bits|= OPTION_TABLE_LOCK;
thd->variables.option_bits|= OPTION_TABLE_LOCK | OPTION_NOT_AUTOCOMMIT;
thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
res= lock_tables_open_and_lock_tables(thd, all_tables);
......
......@@ -18932,7 +18932,6 @@ free_share(
mysql_mutex_unlock(&innobase_share_mutex);
}
#if 0
/*********************************************************************//**
Returns number of THR_LOCK locks used for one instance of InnoDB table.
InnoDB no longer relies on THR_LOCK locks so 0 value is returned.
......@@ -18948,7 +18947,6 @@ ha_innobase::lock_count(void) const
{
return 0;
}
#endif
/*****************************************************************//**
Supposed to convert a MySQL table lock stored in the 'lock' field of the
......@@ -19196,8 +19194,6 @@ ha_innobase::store_lock(
lock.type = lock_type;
}
*to++= &lock;
if (!trx_is_started(trx)
&& (m_prebuilt->select_lock_type != LOCK_NONE
|| m_prebuilt->stored_select_lock_type != LOCK_NONE)) {
......
......@@ -274,7 +274,7 @@ class ha_innobase: public handler
void free_foreign_key_create_info(char* str);
//uint lock_count(void) const;
uint lock_count(void) const;
THR_LOCK_DATA** store_lock(
THD* thd,
......
......@@ -46,7 +46,6 @@ a b
1 10
2 20
3 30
4 40
insert into t2 values (1);
ERROR HY000: Table 't2' was not locked with LOCK TABLES
commit;
......@@ -59,7 +58,6 @@ a b
1 10
2 20
3 30
4 40
select * from t2;
a
1
......@@ -72,7 +70,6 @@ a b
1 10
2 20
3 30
4 40
5 50
select * from t2;
a
......@@ -84,7 +81,6 @@ a b
1 10
2 20
3 30
4 40
5 50
select * from t2;
a
......
......@@ -2,8 +2,8 @@ drop table if exists t1,t3;
CREATE TABLE t3(a int,c int,d int)engine=TOKUDB;
lock table t3 read;
create temporary table t1 engine=tokudb as SELECT 1;
unlock tables;
select * from t1;
1
1
unlock tables;
drop table t1,t3;
......@@ -7,7 +7,7 @@ enable_warnings;
CREATE TABLE t3(a int,c int,d int)engine=TOKUDB;
lock table t3 read;
create temporary table t1 engine=tokudb as SELECT 1;
select * from t1;
unlock tables;
select * from t1;
drop table t1,t3;
\ No newline at end of file
drop table t1,t3;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment