mirror of
https://github.com/MariaDB/server.git
synced 2025-02-02 03:51:50 +01:00
1b5f2b9030
Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB table cause warnings in errlog Concurrent execution of LOCK TABLES ... READ statement and DML statements affecting the same InnoDB table on debug builds of MySQL server might lead to "Found lock of type 6 that is write and read locked" warnings appearing in error log. The problem is that the table-level locking code allows a thread to acquire TL_READ_NO_INSERT lock on a table even if there is another thread which holds TL_WRITE_ALLOW_WRITE lock on the same table. At the same time, the locking code assumes that that such locks are incompatible (for example, see check_locks()). This doesn't lead to any problems other than warnings in error log for debug builds of server since for InnoDB tables TL_READ_NO_INSERT type of lock is only used for LOCK TABLES and for this statement InnoDB also performs its own table-level locking. Unfortunately, the table lock compatibility matrix cannot be updated to disallow TL_READ_NO_INSERT when another thread holds TL_WRITE_ALLOW_WRITE without causing starvation of LOCK TABLE READ in InnoDB under high write load. This patch therefore contains no code changes. The issue will be fixed later when LOCK TABLE READ has been updated to not use table locks. This bug will therefore be marked as "To be fixed later". Code comment in thr_lock.c expanded to clarify the issue and a test case based on the bug description added to innodb_mysql_lock.test. Note that a global suppression rule has been added to both MTR v1 and v2 for the "Found lock of type 6 that is write and read locked" warning. These suppression rules must be removed once this bug is properly fixed.
121 lines
2.9 KiB
Text
121 lines
2.9 KiB
Text
-- source include/have_innodb.inc
|
|
|
|
# Save the initial number of concurrent sessions.
|
|
--source include/count_sessions.inc
|
|
|
|
--echo #
|
|
--echo # Bug #22876 Four-way deadlock
|
|
--echo #
|
|
|
|
--disable_warnings
|
|
DROP TABLE IF EXISTS t1;
|
|
--enable_warnings
|
|
|
|
connect (con1,localhost,root,,);
|
|
connect (con2,localhost,root,,);
|
|
connect (con3,localhost,root,,);
|
|
|
|
--echo # Connection 1
|
|
connection con1;
|
|
set @@autocommit=0;
|
|
CREATE TABLE t1(s1 INT UNIQUE) ENGINE=innodb;
|
|
INSERT INTO t1 VALUES (1);
|
|
|
|
--echo # Connection 2
|
|
connection con2;
|
|
set @@autocommit=0;
|
|
INSERT INTO t1 VALUES (2);
|
|
--send INSERT INTO t1 VALUES (1)
|
|
|
|
--echo # Connection 3
|
|
connection con3;
|
|
set @@autocommit=0;
|
|
--send DROP TABLE t1
|
|
|
|
--echo # Connection 1
|
|
connection con1;
|
|
let $wait_condition=
|
|
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
|
WHERE info = "INSERT INTO t1 VALUES (1)" and
|
|
state = "update";
|
|
--source include/wait_condition.inc
|
|
let $wait_condition=
|
|
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
|
WHERE info = "DROP TABLE t1" and
|
|
state = "Waiting for table";
|
|
--source include/wait_condition.inc
|
|
--echo # Connection 1 is now holding the lock.
|
|
--echo # Issuing insert from connection 1 while connection 2&3
|
|
--echo # is waiting for the lock should give a deadlock error.
|
|
--error ER_LOCK_DEADLOCK
|
|
INSERT INTO t1 VALUES (2);
|
|
|
|
--echo # Cleanup
|
|
connection con2;
|
|
--reap
|
|
commit;
|
|
set @@autocommit=1;
|
|
connection con1;
|
|
commit;
|
|
set @@autocommit=1;
|
|
connection con3;
|
|
--reap
|
|
set @@autocommit=1;
|
|
connection default;
|
|
|
|
disconnect con1;
|
|
disconnect con3;
|
|
|
|
--echo #
|
|
--echo # Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB
|
|
--echo # table cause warnings in errlog
|
|
--echo #
|
|
|
|
--echo #
|
|
--echo # Note that this test for now relies on a global suppression of
|
|
--echo # the warning "Found lock of type 6 that is write and read locked"
|
|
--echo # This suppression rule can be removed once Bug#42147 is properly
|
|
--echo # fixed. See bug page for more info.
|
|
--echo #
|
|
|
|
--disable_warnings
|
|
DROP TABLE IF EXISTS t1;
|
|
--enable_warnings
|
|
|
|
CREATE TABLE t1 (i INT) engine= innodb;
|
|
|
|
--echo # Connection 2
|
|
--echo # Get user-level lock
|
|
connection con2;
|
|
SELECT get_lock('bug42147_lock', 60);
|
|
|
|
--echo # Connection 1
|
|
connection default;
|
|
--send INSERT INTO t1 SELECT get_lock('bug42147_lock', 60)
|
|
|
|
--echo # Connection 2
|
|
connection con2;
|
|
let $wait_condition=
|
|
SELECT COUNT(*) > 0 FROM information_schema.processlist
|
|
WHERE state = 'User lock'
|
|
AND info = 'INSERT INTO t1 SELECT get_lock(\'bug42147_lock\', 60)';
|
|
--source include/wait_condition.inc
|
|
LOCK TABLES t1 READ;
|
|
SELECT release_lock('bug42147_lock');
|
|
|
|
--echo # Connection 1
|
|
connection default;
|
|
--reap
|
|
|
|
--echo # Connection 2
|
|
connection con2;
|
|
UNLOCK TABLES;
|
|
|
|
--echo # Connection 1
|
|
connection default;
|
|
disconnect con2;
|
|
DROP TABLE t1;
|
|
|
|
# Check that all connections opened by test cases in this file are really
|
|
# gone so execution of other tests won't be affected by their presence.
|
|
--source include/wait_until_count_sessions.inc
|