List:Commits« Previous MessageNext Message »
From:Magne Mahre Date:February 19 2009 11:23am
Subject:bzr commit into mysql-6.0 branch (magne.mahre:2729) Bug#37433
View as plain text  
#At file:///export/home/tmp/z/mysql-6.0-runtime/ based on revid:alik@stripped

 2729 Magne Mahre	2009-02-19
      Bug #37433  	Deadlock between open_table, close_open_tables, 
                      get_table_share, drop_open_table
            
      In the partition handler code, LOCK_open and share->LOCK_ha_data
      are acquired in the wrong order in certain cases.  When doing a
      multi-row INSERT (i.e a INSERT..SELECT) in a table with auto-
      increment column(s). the increments must be in a monotonically
      continuous increasing sequence (i.e it can't have "holes"). To
      achieve this, a lock is held for the duration of the operation.
      share->LOCK_ha_data was used for this purpose.
            
      Whenever there was a need to open a view _during_ the operation
      (views are not currently pre-opened the way tables are), and
      LOCK_open was grabbed, a deadlock could occur.  share->LOCK_ha_data
      is other places used _while_ holding LOCK_open.
            
      A new mutex was introduced in the HA_DATA_PARTITION structure,
      for exclusive use of the autoincrement data fields, so we don't
      need to overload the use of LOCK_ha_data here.
            
      A module test case has not been supplied, since the problem occurs
      as a result of a race condition, and testing for this condition 
      is thus not deterministic.   Testing for it could be done by
      setting up a test case as described in the bug report.
modified:
  sql/ha_partition.cc
  sql/ha_partition.h

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2009-02-02 12:28:30 +0000
+++ b/sql/ha_partition.cc	2009-02-19 11:22:46 +0000
@@ -2536,6 +2536,7 @@ int ha_partition::open(const char *name,
     }
     DBUG_PRINT("info", ("table_share->ha_data 0x%p", ha_data));
     bzero(ha_data, sizeof(HA_DATA_PARTITION));
+    pthread_mutex_init(&ha_data->mutex, MY_MUTEX_INIT_FAST);
   }
   if (is_not_tmp_table)
     pthread_mutex_unlock(&table_share->LOCK_ha_data);

=== modified file 'sql/ha_partition.h'
--- a/sql/ha_partition.h	2009-02-02 12:28:30 +0000
+++ b/sql/ha_partition.h	2009-02-19 11:22:46 +0000
@@ -45,6 +45,7 @@ typedef struct st_ha_data_partition
 {
   ulonglong next_auto_inc_val;                 /**< first non reserved value */
   bool auto_inc_initialized;
+  pthread_mutex_t mutex;
 } HA_DATA_PARTITION;
 
 #define PARTITION_BYTES_IN_POS 2
@@ -908,14 +909,16 @@ private:
   virtual int reset_auto_increment(ulonglong value);
   virtual void lock_auto_increment()
   {
+    HA_DATA_PARTITION *ha_data; 
     /* lock already taken */
     if (auto_increment_safe_stmt_log_lock)
       return;
     DBUG_ASSERT(table_share->ha_data && !auto_increment_lock);
     if(table_share->tmp_table == NO_TMP_TABLE)
     {
+      ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
       auto_increment_lock= TRUE;
-      pthread_mutex_lock(&table_share->LOCK_ha_data);
+      pthread_mutex_lock(&ha_data->mutex);
     }
   }
   virtual void unlock_auto_increment()
@@ -928,7 +931,8 @@ private:
     */
     if(auto_increment_lock && !auto_increment_safe_stmt_log_lock)
     {
-      pthread_mutex_unlock(&table_share->LOCK_ha_data);
+      HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data; 
+      pthread_mutex_unlock(&ha_data->mutex);
       auto_increment_lock= FALSE;
     }
   }

Thread
bzr commit into mysql-6.0 branch (magne.mahre:2729) Bug#37433Magne Mahre19 Feb