List:Internals« Previous MessageNext Message »
From:ingo Date:June 22 2005 2:02pm
Subject:bk commit into 4.1 tree (ingo:1.2296) 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.2296 05/06/22 14:02:48 ingo@stripped +4 -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.
  Table changes will now request for statistics updates only,
  instead of doing it themselves. The real update is then done
  with the next info().

  sql/ha_heap.h
    1.33 05/06/22 14:02:44 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.57 05/06/22 14:02:44 ingo@stripped +26 -5
    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.
    Table changes will now request for statistics updates only,
    instead of doing it themselves. The real update is then done
    with the next info().

  mysql-test/t/heap_hash.test
    1.9 05/06/22 14:02:44 ingo@stripped +2 -0
    Bug#10178 - failure to find a row in heap table by concurrent UPDATEs
    Added a FLUSH TABLES due to different place of update_key_stats(),
    which showed up in different results between normal and
    ps-protocol tests.

  mysql-test/r/heap_hash.result
    1.13 05/06/22 14:02:44 ingo@stripped +12 -11
    Bug#10178 - failure to find a row in heap table by concurrent UPDATEs
    Updated test results due to different place of update_key_stats().

# 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.56/sql/ha_heap.cc	Sun Jun  5 19:38:38 2005
+++ 1.57/sql/ha_heap.cc	Wed Jun 22 14:02:44 2005
@@ -60,7 +60,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);
 }
@@ -112,6 +120,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)
@@ -125,7 +135,7 @@
   res= heap_write(file,buf);
   if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
               file->s->records)
-    update_key_stats();
+    key_stats_ok= FALSE;
   return res;
 }
 
@@ -138,7 +148,7 @@
   res= heap_update(file,old_data,new_data);
   if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
               file->s->records)
-    update_key_stats();
+    key_stats_ok= FALSE;
   return res;
 }
 
@@ -149,7 +159,7 @@
   res= heap_delete(file,buf);
   if (!res && table->tmp_table == NO_TMP_TABLE && 
       ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
-    update_key_stats();
+    key_stats_ok= FALSE;
   return res;
 }
 
@@ -262,6 +272,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)
@@ -273,7 +290,7 @@
 {
   heap_clear(file);
   if (table->tmp_table == NO_TMP_TABLE)
-    update_key_stats();
+    key_stats_ok= FALSE;
   return 0;
 }
 
@@ -433,7 +450,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.32/sql/ha_heap.h	Tue May 24 21:21:11 2005
+++ 1.33/sql/ha_heap.h	Wed Jun 22 14:02:44 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)

--- 1.12/mysql-test/r/heap_hash.result	Tue Feb  8 21:44:49 2005
+++ 1.13/mysql-test/r/heap_hash.result	Wed Jun 22 14:02:44 2005
@@ -231,18 +231,19 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ref	a	a	8	const	1	Using where
 insert into t1 select * from t1;
+flush tables;
 explain select * from t1 where a='aaaa';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	a	a	8	const	1	Using where
+1	SIMPLE	t1	ref	a	a	8	const	2	Using where
 explain select * from t1 where a='aaab';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	a	a	8	const	1	Using where
+1	SIMPLE	t1	ref	a	a	8	const	2	Using where
 explain select * from t1 where a='aaac';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	a	a	8	const	1	Using where
+1	SIMPLE	t1	ref	a	a	8	const	2	Using where
 explain select * from t1 where a='aaad';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	a	a	8	const	1	Using where
+1	SIMPLE	t1	ref	a	a	8	const	2	Using where
 flush tables;
 explain select * from t1 where a='aaaa';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
@@ -261,16 +262,16 @@
 insert into t1 select * from t2;
 explain select * from t1 where a='aaaa';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	a	a	8	const	1	Using where
+1	SIMPLE	t1	ref	a	a	8	const	2	Using where
 explain select * from t1 where a='aaab';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	a	a	8	const	1	Using where
+1	SIMPLE	t1	ref	a	a	8	const	2	Using where
 explain select * from t1 where a='aaac';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	a	a	8	const	1	Using where
+1	SIMPLE	t1	ref	a	a	8	const	2	Using where
 explain select * from t1 where a='aaad';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	a	a	8	const	1	Using where
+1	SIMPLE	t1	ref	a	a	8	const	2	Using where
 drop table t1, t2;
 create table t1 (
 id int unsigned not null primary key auto_increment, 
@@ -345,15 +346,15 @@
 show index from t3;
 Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment
 t3	1	a	1	a	NULL	NULL	NULL	NULL		HASH	
-t3	1	a	2	b	NULL	15	NULL	NULL		HASH	
+t3	1	a	2	b	NULL	13	NULL	NULL		HASH	
 show index from t3;
 Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment
 t3	1	a	1	a	NULL	NULL	NULL	NULL		HASH	
-t3	1	a	2	b	NULL	15	NULL	NULL		HASH	
+t3	1	a	2	b	NULL	13	NULL	NULL		HASH	
 explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a =
concat('',t1.name) and t3.b=t1.name;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	ref	heap_idx	heap_idx	20	const	7	Using where
-1	SIMPLE	t3	ref	a	a	40	func,const	6	Using where
+1	SIMPLE	t3	ref	a	a	40	func,const	7	Using where
 drop table t1, t2, t3;
 create temporary table t1 ( a int, index (a) ) engine=memory;
 insert into t1 values (1),(2),(3),(4),(5);

--- 1.8/mysql-test/t/heap_hash.test	Tue Feb  8 21:44:49 2005
+++ 1.9/mysql-test/t/heap_hash.test	Wed Jun 22 14:02:44 2005
@@ -169,6 +169,8 @@
 explain select * from t1 where a='aaad';
 insert into t1 select * from t1;
 
+# avoid statistics differences between normal and ps-protocol tests
+flush tables;
 explain select * from t1 where a='aaaa';
 explain select * from t1 where a='aaab';
 explain select * from t1 where a='aaac';
Thread
bk commit into 4.1 tree (ingo:1.2296) BUG#10178ingo22 Jun