diff --git a/mysql-test/r/lock_sync.result b/mysql-test/r/lock_sync.result index 0b57b38f5ec..4eddbd170d9 100644 --- a/mysql-test/r/lock_sync.result +++ b/mysql-test/r/lock_sync.result @@ -60,6 +60,8 @@ release_lock("lock_bug45143_wait") 1 # Switch to connection 'con_bug45143_1'. # Reap INSERT statement. +Warnings: +Note 1592 Statement may not be safe to log in statement format. # Switch to connection 'con_bug45143_3'. # Reap LOCK TABLES statement. unlock tables; @@ -69,3 +71,23 @@ 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; +CREATE TABLE t1(id INT); +CREATE TABLE t2(id INT); +# Connection con2 +START TRANSACTION; +SELECT * FROM t1; +id +# Connection default +# Sending: +ALTER TABLE t1 ADD COLUMN j INT; +# Connection con2 +# This used to cause a deadlock. +INSERT INTO t2 SELECT * FROM t1; +COMMIT; +# Connection default +# Reaping ALTER TABLE t1 ADD COLUMN j INT +DROP TABLE t1, t2; diff --git a/mysql-test/t/lock_sync.test b/mysql-test/t/lock_sync.test index 460c0175808..6974a8ec968 100644 --- a/mysql-test/t/lock_sync.test +++ b/mysql-test/t/lock_sync.test @@ -4,6 +4,10 @@ --source include/have_debug_sync.inc # We need InnoDB to be able use TL_WRITE_ALLOW_WRITE type of locks in our tests. --source include/have_innodb.inc +# The test for Bug#50821 requires binary logging turned on. +# With binary logging on, sub-queries in DML statements acquire +# TL_READ_NO_INSERT which was needed to reproduce this deadlock bug. +--source include/have_log_bin.inc # Until bug#41971 'Thread state on embedded server is always "Writing to net"' # is fixed this test can't be run on embedded version of server. --source include/not_embedded.inc @@ -118,6 +122,49 @@ drop view v1; drop table t1; +--echo # +--echo # Bug#50821 Deadlock between LOCK TABLES and ALTER TABLE +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1(id INT); +CREATE TABLE t2(id INT); + +--echo # Connection con2 +connect (con2, localhost, root); +START TRANSACTION; +SELECT * FROM t1; + +--echo # Connection default +connection default; +--echo # Sending: +--send ALTER TABLE t1 ADD COLUMN j INT + +--echo # Connection con2 +connection con2; +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table" + AND info = "ALTER TABLE t1 ADD COLUMN j INT"; +--source include/wait_condition.inc + +--echo # This used to cause a deadlock. +INSERT INTO t2 SELECT * FROM t1; + +COMMIT; + +--echo # Connection default +connection default; +--echo # Reaping ALTER TABLE t1 ADD COLUMN j INT +--reap + +DROP TABLE t1, t2; +disconnect con2; + + # 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 diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 6d62476ecf3..901620d3a93 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -549,7 +549,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, Request /------- H|++++ WRITE_ALLOW_WRITE - e|+++- WRITE_ALLOW_READ + e|++++ WRITE_ALLOW_READ l|+++- WRITE_CONCURRENT_INSERT d|++++ WRITE_DELAYED |||| @@ -572,8 +572,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || (lock->write.data->type <= TL_WRITE_DELAYED && (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) || - (lock->write.data->type != TL_WRITE_CONCURRENT_INSERT && - lock->write.data->type != TL_WRITE_ALLOW_READ)))) + (lock->write.data->type != TL_WRITE_CONCURRENT_INSERT)))) { /* Already got a write lock */ (*lock->read.last)=data; /* Add to running FIFO */ data->prev=lock->read.last;