#At file:///export/home/z/mysql-next-bugfixing-bug46272/ based on revid:dlenev@stripped
2803 Jon Olav Hauglid 2009-08-28
Bug #46272 MySQL 5.4.4, new MDL: unnecessary deadlock
The problem was that ALTER TABLE calls wait_while_table_is_used()
which set TABLE_SHARE's version = 0. This happened before
ALTER TABLE starts waiting for the shared lock to disappear inside
upgrade_shared_lock_to_exclusive(). The following UPDATE noticed
that share->version now was different from refresh_version and
called Open_table_context::request_backoff_action() which
triggered the DEADLOCK error.
This patch removes the setting of TABLE_SHARE's version to 0
inside wait_while_table_is_used(), since this anyway will
be done by close_all_tables_for_name() which is called right
after the return from wait_while_table_is_used().
Test case added to mdl_sync.test.
modified:
mysql-test/r/mdl_sync.result
mysql-test/t/mdl_sync.test
sql/sql_base.cc
=== modified file 'mysql-test/r/mdl_sync.result'
--- a/mysql-test/r/mdl_sync.result 2009-08-27 06:22:17 +0000
+++ b/mysql-test/r/mdl_sync.result 2009-08-28 08:55:46 +0000
@@ -233,3 +233,24 @@ drop table t2;
# Switching to connection 'default'.
# Clean-up.
drop table t1;
+#
+# 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);
+# Connection 1
+SET autocommit=0;
+BEGIN;
+UPDATE t1 SET c3=c3+1 WHERE c2=3;
+# Connection 2
+SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive_wait SIGNAL lock_wait';
+ALTER TABLE t1 ADD COLUMN e INT;
+# Connection 1
+SET DEBUG_SYNC= 'now WAIT_FOR lock_wait';
+UPDATE t1 SET c3=c3+1 WHERE c2=4;
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+DROP TABLE t1;
+SET DEBUG_SYNC= 'RESET';
=== modified file 'mysql-test/t/mdl_sync.test'
--- a/mysql-test/t/mdl_sync.test 2009-08-27 06:22:17 +0000
+++ b/mysql-test/t/mdl_sync.test 2009-08-28 08:55:46 +0000
@@ -438,6 +438,42 @@ disconnect con46044;
disconnect con46044_2;
drop table t1;
+--echo #
+--echo # Bug#46272 MySQL 5.4.4, new MDL: unnecessary deadlock
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+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);
+connect (con1,localhost,root,,test,,);
+
+--echo # Connection 1
+connection default;
+SET autocommit=0;
+BEGIN;
+UPDATE t1 SET c3=c3+1 WHERE c2=3;
+
+--echo # Connection 2
+connection con1;
+SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive_wait SIGNAL lock_wait';
+--send ALTER TABLE t1 ADD COLUMN e INT
+
+--echo # Connection 1
+connection default;
+SET DEBUG_SYNC= 'now WAIT_FOR lock_wait';
+UPDATE t1 SET c3=c3+1 WHERE c2=4;
+ROLLBACK;
+
+connection con1;
+reap;
+
+connection default;
+disconnect con1;
+DROP TABLE t1;
+SET DEBUG_SYNC= 'RESET';
# 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.
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2009-08-27 06:22:17 +0000
+++ b/sql/sql_base.cc 2009-08-28 08:55:46 +0000
@@ -2094,11 +2094,6 @@ bool wait_while_table_is_used(THD *thd,
table->s->table_name.str, table->s,
table->db_stat, table->s->version));
- /* Ensure no one can reopen table before it's removed */
- pthread_mutex_lock(&LOCK_open);
- table->s->version= 0;
- pthread_mutex_unlock(&LOCK_open);
-
old_lock_type= table->reginfo.lock_type;
mysql_lock_abort(thd, table, TRUE); /* end threads waiting on lock */
Attachment: [text/bzr-bundle] bzr/jon.hauglid@sun.com-20090828085546-uq0jgfc02dgoucl6.bundle
| Thread |
|---|
| • bzr commit into mysql-5.4 branch (jon.hauglid:2803) Bug#46272 | Jon Olav Hauglid | 28 Aug |