List:Commits« Previous MessageNext Message »
From:Konstantin Osipov Date:November 20 2009 8:13pm
Subject:bzr commit into mysql-5.6-next-mr branch (kostja:2927)
View as plain text  
#At file:///opt/local/work/next-mr-kostja/ based on revid:kostja@stripped

 2927 Konstantin Osipov	2009-11-20
      Backport of:
      ------------------------------------------------------------
      revno: 2476.1116.1
      committer: davi@stripped/endora.local
      timestamp: Fri 2007-12-14 10:10:19 -0200
      message:
      DROP TABLE under LOCK TABLES simultaneous to a FLUSH TABLES
      WITH READ LOCK (global read lock) can lead to a deadlock.
      
      The solution is to not wait for the global read lock if the
      thread is holding any locked tables.
      
      Related to bugs 23713 and 32395. This issues is being fixed
      only on 6.0 because it depends on the fix for bug 25858 --
      which was fixed only on 6.0.

    modified:
      mysql-test/r/lock_multi.result
      mysql-test/t/lock_multi.test
      sql/sql_table.cc
=== modified file 'mysql-test/r/lock_multi.result'
--- a/mysql-test/r/lock_multi.result	2009-11-20 19:51:12 +0000
+++ b/mysql-test/r/lock_multi.result	2009-11-20 20:12:57 +0000
@@ -210,3 +210,12 @@ select @tlwa < @tlwb;
 @tlwa < @tlwb
 1
 End of 5.1 tests
+drop table if exists t1;
+create table t1 (i int);
+connection: default
+lock tables t1 write;
+connection: flush
+flush tables with read lock;;
+connection: default
+flush tables;
+drop table t1;

=== modified file 'mysql-test/t/lock_multi.test'
--- a/mysql-test/t/lock_multi.test	2009-11-20 19:51:12 +0000
+++ b/mysql-test/t/lock_multi.test	2009-11-20 20:12:57 +0000
@@ -636,6 +636,41 @@ select @tlwa < @tlwb;
 
 --echo End of 5.1 tests
 
+#
+# Test that DROP TABLES does not wait for a impending FLUSH TABLES
+# WITH READ LOCK
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (i int);
+connect (flush,localhost,root,,test,,);
+connection default;
+--echo connection: default
+lock tables t1 write;
+connection flush;
+--echo connection: flush
+--send flush tables with read lock;
+connection default;
+--echo connection: default
+let $wait_condition=
+  select count(*) = 1 from information_schema.processlist
+  where state = "Flushing tables";
+--source include/wait_condition.inc
+flush tables;
+let $wait_condition=
+  select count(*) = 1 from information_schema.processlist
+  where state = "Flushing tables";
+--source include/wait_condition.inc
+drop table t1;
+let $wait_condition=
+  select count(*) = 0 from information_schema.processlist
+  where state = "Flushing tables";
+--source include/wait_condition.inc
+connection flush;
+--reap
+connection default;
+disconnect flush;
 # Wait till all disconnects are completed
 --source include/wait_until_count_sessions.inc
-

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2009-11-10 07:31:33 +0000
+++ b/sql/sql_table.cc	2009-11-20 20:12:57 +0000
@@ -1766,7 +1766,8 @@ void write_bin_log(THD *thd, bool clear_
     If a table is in use, we will wait for all users to free the table
     before dropping it
 
-    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set.
+    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
+    not if under LOCK TABLES.
 
   RETURN
     FALSE OK.  In this case ok packet is sent to user
@@ -1777,7 +1778,7 @@ void write_bin_log(THD *thd, bool clear_
 bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
                     my_bool drop_temporary)
 {
-  bool error= FALSE, need_start_waiters= FALSE;
+  bool error= FALSE, need_start_waiting= FALSE;
   Drop_table_error_handler err_handler(thd->get_internal_handler());
   DBUG_ENTER("mysql_rm_table");
 
@@ -1785,13 +1786,9 @@ bool mysql_rm_table(THD *thd,TABLE_LIST 
 
   if (!drop_temporary)
   {
-    if ((error= wait_if_global_read_lock(thd, 0, 1)))
-    {
-      my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
+    if (!thd->locked_tables &&
+        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
       DBUG_RETURN(TRUE);
-    }
-    else
-      need_start_waiters= TRUE;
   }
 
   /*
@@ -1804,7 +1801,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST 
   thd->pop_internal_handler();
 
 
-  if (need_start_waiters)
+  if (need_start_waiting)
     start_waiting_global_read_lock(thd);
 
   if (error)


Attachment: [text/bzr-bundle] bzr/kostja@sun.com-20091120201257-yy7t8dgotsotg0so.bundle
Thread
bzr commit into mysql-5.6-next-mr branch (kostja:2927)Konstantin Osipov20 Nov