Bug #48210 | FLUSH TABLES WITH READ LOCK deadlocks against concurrent CREATE PROCEDURE | ||
---|---|---|---|
Submitted: | 21 Oct 2009 17:32 | Modified: | 7 Mar 2010 1:42 |
Reporter: | Matthias Leich | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Locking | Severity: | S3 (Non-critical) |
Version: | mysql-6.0-codebase-bugfixing | OS: | Any |
Assigned to: | Jon Olav Hauglid | CPU Architecture: | Any |
Tags: | locking |
[21 Oct 2009 17:32]
Matthias Leich
[27 Oct 2009 12:24]
Jon Olav Hauglid
To reproduce the deadlock using MTR add these sync points: === modified file 'sql/lock.cc' --- sql/lock.cc 2009-10-12 09:08:34 +0000 +++ sql/lock.cc 2009-10-27 12:03:46 +0000 @@ -265,6 +265,8 @@ &write_lock_used))) break; + DEBUG_SYNC(thd, "grl_check"); + if (global_read_lock && write_lock_used && ! (flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK)) { === modified file 'sql/sql_base.cc' --- sql/sql_base.cc 2009-10-25 13:41:27 +0000 +++ sql/sql_base.cc 2009-10-27 12:04:44 +0000 @@ -935,6 +935,7 @@ bool found= TRUE; DBUG_ENTER("close_cached_tables"); DBUG_ASSERT(thd || (!wait_for_refresh && !tables)); + DEBUG_SYNC(thd, "close_cached_tables"); if (!have_lock) pthread_mutex_lock(&LOCK_open); The execute the following test case: --source include/have_debug_sync.inc connect (con2, localhost, root); connect (con3, localhost, root); --echo # Connection 2 connection con2; SET DEBUG_SYNC= 'grl_check SIGNAL table_opened WAIT_FOR grl_locked'; --send CREATE PROCEDURE p1() SELECT 1 --echo # Now connection 2 has opened mysql.proc --echo # Connection 1 connection default; SET DEBUG_SYNC='now WAIT_FOR table_opened'; SET DEBUG_SYNC='close_cached_tables SIGNAL grl_locked WAIT_FOR grl_waiting'; --send FLUSH TABLES WITH READ LOCK --echo # Now connection 1 has the GRL, about to close cached tables --echo # Connection 3 connection con3; --echo # Wait until connection 2 is sleeping, waiting for GRL to go away --sleep 1 --echo # Then let connection 1 change refresh_version SET DEBUG_SYNC='now SIGNAL grl_waiting'; --echo # DEADLOCK
[28 Oct 2009 15:46]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/88497 3685 Jon Olav Hauglid 2009-10-28 Bug #48210 FLUSH TABLES WITH READ LOCK deadlocks against concurrent CREATE PROCEDURE This deadlock occured between a) CREATE PROCEDURE (or other commands listed below) b) FLUSH TABLES WITH READ LOCK If the execution of them happened in the following order: - a) opens a table (e.g. mysql.proc) - b) locks the global read lock (or GRL) - a) sleeps inside wait_if_global_read_lock() - b) increases refresh_version and sleeps waiting for old tables to go away Note that a) must start waiting on the GRL before FLUSH increases refresh_version. Otherwise a) won't wait on the GRL and instead close its tables for reopen, allowing FLUSH to complete and thus avoid the deadlock. With this patch the deadlock is avoided by making CREATE PROCEDURE acquire a protection against global read locks before it starts executing. This means that FLUSH TABLES WITH READ LOCK will have to wait until CREATE PROCEDURE completes before acquiring the global read lock, thereby avoiding the deadlock. This is implemented by introducing a new SQL command flag called CF_PROTECT_AGAINST_GRL. Commands marked with this flag will acquire a GRL protection in the beginning of mysql_execute_command(). This patch adds the flag to CREATE, ALTER and DROP for PROCEDURE and FUNCTION, as well as CREATE USER, DROP USER, RENAME USER and REVOKE ALL. All these commands either call open_grant_tables() or open_system_table_for_updated() which make them susceptible for this deadlock. The patch also adds the CF_PROTECT_AGAINST_GRL flag to a number of commands that previously acquired GRL protection in their respective SQLCOM case in mysql_execute_command(). Test case that checks for GRL protection for CREATE PROCEDURE and CREATE USER added to mdl_sync.test.
[29 Oct 2009 7:51]
Jon Olav Hauglid
Pushed to mysql-6.0-codebase-bugfixing (6.0.14-alpha)
[30 Oct 2009 8:01]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/88684 3690 Jon Olav Hauglid 2009-10-30 Postfix for Bug#48210 FLUSH TABLES WITH READ LOCK deadlocks against concurrent CREATE PROCEDURE Rewrote the second test to use DROP PROCEDURE instead of CREATE USER as CREATE USER does not work with embedded server.
[31 Oct 2009 8:20]
Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20091031081410-qkxmjsdzjmj840aq) (version source revid:jon.hauglid@sun.com-20091030080112-uf5pl9qyw8ha5rus) (merge vers: 6.0.14-alpha) (pib:13)
[2 Nov 2009 21:01]
Paul DuBois
Noted in 6.0.14 changelog. FLUSH TABLES WITH READ LOCK could deadlock when executed against concurrent DDL statements for stored routines or account-management statements.
[10 Dec 2009 14:10]
Jon Olav Hauglid
Pushed to mysql-next-4284 (5.6.0-beta).
[16 Feb 2010 16:50]
Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20100216101445-2ofzkh48aq2e0e8o) (version source revid:kostja@sun.com-20091211154405-c9yhiewr9o5d20rq) (merge vers: 6.0.14-alpha) (pib:16)
[16 Feb 2010 16:59]
Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100216101208-33qkfwdr0tep3pf2) (version source revid:kostja@sun.com-20091211103945-198h3pt8w7ypk20u) (pib:16)
[17 Feb 2010 1:17]
Paul DuBois
Setting report to Need Merge pending push of Celosia into release tree.
[6 Mar 2010 10:54]
Bugs System
Pushed into 5.5.3-m3 (revid:alik@sun.com-20100306103849-hha31z2enhh7jwt3) (version source revid:vvaintroub@mysql.com-20100216221947-luyhph0txl2c5tc8) (merge vers: 5.5.99-m3) (pib:16)
[7 Mar 2010 1:42]
Paul DuBois
Noted in 5.5.3 changelog.
[13 Apr 2010 4:59]
Paul DuBois
Correction: Not present in any 5.5.x release. 5.5.3 changelog entry removed.