List:Commits« Previous MessageNext Message »
From:Mattias Jonsson Date:August 17 2010 4:07pm
Subject:bzr commit into mysql-5.5-bugfixing branch (mattias.jonsson:3184)
View as plain text  
#At file:///Users/mattiasj/mysql-bzr/b54747-5.5-bf/ based on revid:joerg@stripped

 3184 Mattias Jonsson	2010-08-17 [merge]
      merge

    modified:
      mysql-test/r/partition_debug_sync.result
      mysql-test/t/partition_debug_sync.test
      sql/sql_base.cc
      sql/sql_partition.cc
      sql/sql_table.cc
=== modified file 'mysql-test/r/partition_debug_sync.result'
--- a/mysql-test/r/partition_debug_sync.result	2010-07-01 13:53:46 +0000
+++ b/mysql-test/r/partition_debug_sync.result	2010-08-17 15:54:04 +0000
@@ -1,6 +1,38 @@
 DROP TABLE IF EXISTS t1, t2;
 SET DEBUG_SYNC= 'RESET';
 #
+# Bug#54747: Deadlock between REORGANIZE PARTITION and
+#            SELECT is not detected
+#
+SET GLOBAL innodb_thread_concurrency = 1;
+CREATE TABLE t1
+(user_num BIGINT,
+hours SMALLINT,
+KEY user_num (user_num))
+ENGINE = InnoDB   
+PARTITION BY RANGE COLUMNS (hours)
+(PARTITION hour_003 VALUES LESS THAN (3),
+PARTITION hour_004 VALUES LESS THAN (4),
+PARTITION hour_005 VALUES LESS THAN (5),
+PARTITION hour_last VALUES LESS THAN (MAXVALUE));
+LOAD DATA LOCAL INFILE '/Users/mattiasj/mysql-bzr/test-55-bugfixing/b/mysql-test/var/t_part_range.load' 
+INTO TABLE t1 (user_num, hours);
+# Start a ALTER PARTITION and wait between the copy and rename of table.
+# con1
+SET DEBUG_SYNC= 'wait_while_table_is_used SIGNAL run_select WAIT_FOR select_started';
+ALTER TABLE t1
+REORGANIZE PARTITION hour_003, hour_004 INTO
+(PARTITION oldest VALUES LESS THAN (4));
+# Start a concurrent SELECT
+SET DEBUG_SYNC= 'now WAIT_FOR run_select';
+SET DEBUG_SYNC= 'after_lock_tables_takes_lock SIGNAL select_started';
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+10000
+SET DEBUG_SYNC= 'RESET';
+SET GLOBAL innodb_thread_concurrency = 0;
+DROP TABLE t1;
+#
 # Bug#42438: Crash ha_partition::change_table_ptr
 # Test when remove partitioning is done while drop table is waiting
 # for the table.

=== modified file 'mysql-test/t/partition_debug_sync.test'
--- a/mysql-test/t/partition_debug_sync.test	2010-07-01 13:53:46 +0000
+++ b/mysql-test/t/partition_debug_sync.test	2010-08-17 15:54:04 +0000
@@ -12,6 +12,68 @@ SET DEBUG_SYNC= 'RESET';
 --enable_warnings
 
 --echo #
+--echo # Bug#54747: Deadlock between REORGANIZE PARTITION and
+--echo #            SELECT is not detected
+--echo #
+
+let $thread_concurrency = `SELECT @@innodb_thread_concurrency`;
+SET GLOBAL innodb_thread_concurrency = 1;
+
+CREATE TABLE t1
+(user_num BIGINT,
+ hours SMALLINT,
+ KEY user_num (user_num))
+ENGINE = InnoDB   
+PARTITION BY RANGE COLUMNS (hours)
+(PARTITION hour_003 VALUES LESS THAN (3),
+ PARTITION hour_004 VALUES LESS THAN (4),
+ PARTITION hour_005 VALUES LESS THAN (5),
+ PARTITION hour_last VALUES LESS THAN (MAXVALUE));
+
+--perl
+open( DATA, ">$ENV{MYSQLTEST_VARDIR}/t_part_range.load" ) 
+	|| die "Could not open file $ENV{MYSQLTEST_VARDIR}/t_part_range.load for writing: $!";
+for ( 1..10000 )
+{
+	print DATA ( int(rand(9000000000))+1000000000 ), "\t", ( int(rand(5)) ), "\n";
+}
+close( DATA );
+EOF
+
+eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/t_part_range.load' 
+	INTO TABLE t1 (user_num, hours);
+
+
+--echo # Start a ALTER PARTITION and wait between the copy and rename of table.
+--echo # con1
+
+--connect (con1,localhost,root,,)
+SET DEBUG_SYNC= 'wait_while_table_is_used SIGNAL run_select WAIT_FOR select_started';
+--send
+ALTER TABLE t1
+REORGANIZE PARTITION hour_003, hour_004 INTO
+(PARTITION oldest VALUES LESS THAN (4));
+
+--echo # Start a concurrent SELECT
+
+--connection default
+#START TRANSACTION;
+SET DEBUG_SYNC= 'now WAIT_FOR run_select';
+SET DEBUG_SYNC= 'after_lock_tables_takes_lock SIGNAL select_started';
+SELECT COUNT(*) FROM t1;
+
+--connection con1
+--reap
+
+--disconnect con1
+
+--connection default
+
+SET DEBUG_SYNC= 'RESET';
+eval SET GLOBAL innodb_thread_concurrency = $thread_concurrency;
+DROP TABLE t1;
+
+--echo #
 --echo # Bug#42438: Crash ha_partition::change_table_ptr
 --echo # Test when remove partitioning is done while drop table is waiting
 --echo # for the table.

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2010-08-13 07:50:25 +0000
+++ b/sql/sql_base.cc	2010-08-17 15:54:04 +0000
@@ -2197,6 +2197,8 @@ bool wait_while_table_is_used(THD *thd, 
                        table->s->table_name.str, (ulong) table->s,
                        table->db_stat, table->s->version));
 
+  DEBUG_SYNC(thd, "wait_while_table_is_used");
+
   if (thd->mdl_context.upgrade_shared_lock_to_exclusive(
              table->mdl_ticket, thd->variables.lock_wait_timeout))
     DBUG_RETURN(TRUE);

=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc	2010-08-13 07:50:25 +0000
+++ b/sql/sql_partition.cc	2010-08-17 15:54:04 +0000
@@ -4377,7 +4377,6 @@ static int fast_end_partition(THD *thd, 
                               ALTER_PARTITION_PARAM_TYPE *lpt,
                               bool written_bin_log)
 {
-  int error;
   char tmp_name[80];
   DBUG_ENTER("fast_end_partition");
 
@@ -4386,13 +4385,6 @@ static int fast_end_partition(THD *thd, 
   if (!is_empty)
     query_cache_invalidate3(thd, table_list, 0);
 
-  error= trans_commit_stmt(thd);
-  if (trans_commit_implicit(thd))
-    error= 1;
-
-  if (error)
-    DBUG_RETURN(TRUE);                      /* The error has been reported */
-
   if ((!is_empty) && (!written_bin_log) &&
       (!thd->lex->no_write_to_binlog) &&
     write_bin_log(thd, FALSE, thd->query(), thd->query_length()))
@@ -5535,9 +5527,20 @@ static bool mysql_change_partitions(ALTE
   char path[FN_REFLEN+1];
   int error;
   handler *file= lpt->table->file;
+  THD *thd= lpt->thd;
   DBUG_ENTER("mysql_change_partitions");
 
   build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0);
+
+  /*
+    Turn off recovery logging since rollback of an alter table is to
+    delete the new table so there is no need to log the changes to it.
+
+    This needs to be done before external_lock.
+  */
+  if(ha_enable_transaction(thd, FALSE))
+    DBUG_RETURN(TRUE);
+
   if ((error= file->ha_change_partitions(lpt->create_info, path, &lpt->copied,
                                          &lpt->deleted, lpt->pack_frm_data,
                                          lpt->pack_frm_len)))
@@ -5545,6 +5548,21 @@ static bool mysql_change_partitions(ALTE
     file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR));
     DBUG_RETURN(TRUE);
   }
+
+  if (ha_enable_transaction(thd, TRUE))
+    DBUG_RETURN(TRUE);
+
+  /*
+    Ensure that the new table is saved properly to disk
+    before installing new .FRM and releasing InnoDB's internal latches.
+  */
+  error= trans_commit_stmt(thd);
+  if (trans_commit_implicit(thd))
+    error= 1;
+
+  if (error)
+    DBUG_RETURN(TRUE);                      /* The error has been reported */
+
   DBUG_RETURN(FALSE);
 }
 

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-08-16 12:58:38 +0000
+++ b/sql/sql_table.cc	2010-08-17 15:54:04 +0000
@@ -6902,7 +6902,9 @@ copy_data_between_tables(TABLE *from,TAB
   
   /*
     Ensure that the new table is saved properly to disk so that we
-    can do a rename
+    can do a rename.
+    And release InnoDB's internal latches, to avoid deadlock
+    when waiting on other tables before rename.
   */
   if (trans_commit_stmt(thd))
     error=1;


Attachment: [text/bzr-bundle] bzr/mattias.jonsson@oracle.com-20100817160718-pjrpk8i5m8ux4x40.bundle
Thread
bzr commit into mysql-5.5-bugfixing branch (mattias.jonsson:3184) Mattias Jonsson17 Aug