List:Internals« Previous MessageNext Message »
From:ingo Date:June 10 2005 10:34pm
Subject:bk commit into 4.1 tree (ingo:1.2305) BUG#10178
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of mydev. When mydev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2305 05/06/10 22:32:22 ingo@stripped +2 -0
  Bug#10178 - failure to find a row in heap table by concurrent UPDATEs
  Moved the key statistics update from open() to info().
  The table is not locked in open(). This made wrong stats possible.
  
  No test case for the test suite.
  This happens only with heavy concurrency.
  A test script is added to the bug report.

  sql/ha_heap.h
    1.32 05/06/10 22:31:45 ingo@stripped +3 -1
    Bug#10178 - failure to find a row in heap table by concurrent UPDATEs
    Added an element to track the validity of the key statistics.

  sql/ha_heap.cc
    1.55 05/06/10 22:31:45 ingo@stripped +22 -1
    Bug#10178 - failure to find a row in heap table by concurrent UPDATEs
    Moved the key statistics update from open() to info().
    The table is not locked in open(). This made wrong stats possible.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	ingo
# Host:	chilla.local
# Root:	/home/mydev/mysql-4.1-4100

--- 1.54/sql/ha_heap.cc	Thu Jun  2 03:44:52 2005
+++ 1.55/sql/ha_heap.cc	Fri Jun 10 22:31:45 2005
@@ -62,7 +62,15 @@
   {
     /* Initialize variables for the opened table */
     set_keys_for_scanning();
-    update_key_stats();
+    /*
+      We cannot run update_key_stats() here because we do not have a
+      lock on the table. The 'records' count might just be changed
+      temporarily at this moment and we might get wrong statistics (Bug
+      #10178). Instead we request for update. This will be done in
+      ha_heap::info(), which is always called before key statistics are
+      used.
+    */
+    key_stats_ok= FALSE;
   }
   return (file ? 0 : 1);
 }
@@ -114,6 +122,8 @@
     }
   }
   records_changed= 0;
+  /* At the end of update_key_stats() we can proudly claim they are OK. */
+  key_stats_ok= TRUE;
 }
 
 int ha_heap::write_row(byte * buf)
@@ -264,6 +274,13 @@
   delete_length= info.deleted * info.reclength;
   if (flag & HA_STATUS_AUTO)
     auto_increment_value= info.auto_increment;
+  /*
+    If info() is called for the first time after open(), we will still
+    have to update the key statistics. Hoping that a table lock is now
+    in place.
+  */
+  if (! key_stats_ok)
+    update_key_stats();
 }
 
 int ha_heap::extra(enum ha_extra_function operation)
@@ -435,7 +452,11 @@
       max_key->flag != HA_READ_AFTER_KEY)
     return HA_POS_ERROR;			// Can only use exact keys
   else
+  {
+    /* Assert that info() did run. We need current statistics here. */
+    DBUG_ASSERT(key_stats_ok);
     return key->rec_per_key[key->key_parts-1];
+  }
 }
 
 

--- 1.31/sql/ha_heap.h	Wed May  4 15:05:53 2005
+++ 1.32/sql/ha_heap.h	Fri Jun 10 22:31:45 2005
@@ -29,8 +29,10 @@
   key_map btree_keys;
   /* number of records changed since last statistics update */
   uint    records_changed;
+  bool    key_stats_ok;
 public:
-  ha_heap(TABLE *table): handler(table), file(0), records_changed(0) {}
+  ha_heap(TABLE *table): handler(table), file(0), records_changed(0),
+      key_stats_ok(0) {}
   ~ha_heap() {}
   const char *table_type() const { return "HEAP"; }
   const char *index_type(uint inx)
Thread
bk commit into 4.1 tree (ingo:1.2305) BUG#10178ingo10 Jun