Bug#10178 - failure to find a row in heap table by concurrent UPDATEs
Bug#10568 - Function 'LAST_DAY(date)' does not return NULL for invalid argument. Manual merge.
This commit is contained in:
commit
1c33fbc4c1
@ -295,10 +295,8 @@ C_MODE_END
|
|||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_ATOMIC_ADD
|
#ifdef HAVE_ATOMIC_ADD
|
||||||
#if defined(__ia64__)
|
|
||||||
#define new my_arg_new
|
#define new my_arg_new
|
||||||
#define need_to_restore_new 1
|
#define need_to_restore_new 1
|
||||||
#endif
|
|
||||||
C_MODE_START
|
C_MODE_START
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
C_MODE_END
|
C_MODE_END
|
||||||
|
@ -231,18 +231,19 @@ explain select * from t1 where a='aaad';
|
|||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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 1 Using where
|
||||||
insert into t1 select * from t1;
|
insert into t1 select * from t1;
|
||||||
|
flush tables;
|
||||||
explain select * from t1 where a='aaaa';
|
explain select * from t1 where a='aaaa';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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';
|
explain select * from t1 where a='aaab';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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';
|
explain select * from t1 where a='aaac';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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';
|
explain select * from t1 where a='aaad';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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;
|
flush tables;
|
||||||
explain select * from t1 where a='aaaa';
|
explain select * from t1 where a='aaaa';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
@ -261,16 +262,16 @@ delete from t1;
|
|||||||
insert into t1 select * from t2;
|
insert into t1 select * from t2;
|
||||||
explain select * from t1 where a='aaaa';
|
explain select * from t1 where a='aaaa';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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';
|
explain select * from t1 where a='aaab';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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';
|
explain select * from t1 where a='aaac';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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';
|
explain select * from t1 where a='aaad';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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;
|
drop table t1, t2;
|
||||||
create table t1 (
|
create table t1 (
|
||||||
id int unsigned not null primary key auto_increment,
|
id int unsigned not null primary key auto_increment,
|
||||||
@ -345,14 +346,14 @@ insert into t3 select name, name from t1;
|
|||||||
show index from t3;
|
show index from t3;
|
||||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
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 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;
|
show index from t3;
|
||||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
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 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;
|
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
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 SIMPLE t3 ref a a 44 const,const 6 Using where
|
1 SIMPLE t3 ref a a 44 const,const 7 Using where
|
||||||
1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where
|
1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
create temporary table t1 ( a int, index (a) ) engine=memory;
|
create temporary table t1 ( a int, index (a) ) engine=memory;
|
||||||
|
@ -169,6 +169,8 @@ explain select * from t1 where a='aaac';
|
|||||||
explain select * from t1 where a='aaad';
|
explain select * from t1 where a='aaad';
|
||||||
insert into t1 select * from t1;
|
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='aaaa';
|
||||||
explain select * from t1 where a='aaab';
|
explain select * from t1 where a='aaab';
|
||||||
explain select * from t1 where a='aaac';
|
explain select * from t1 where a='aaac';
|
||||||
|
@ -65,7 +65,15 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
|
|||||||
{
|
{
|
||||||
/* Initialize variables for the opened table */
|
/* Initialize variables for the opened table */
|
||||||
set_keys_for_scanning();
|
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);
|
return (file ? 0 : 1);
|
||||||
}
|
}
|
||||||
@ -118,6 +126,8 @@ void ha_heap::update_key_stats()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
records_changed= 0;
|
records_changed= 0;
|
||||||
|
/* At the end of update_key_stats() we can proudly claim they are OK. */
|
||||||
|
key_stats_ok= TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,7 +142,7 @@ int ha_heap::write_row(byte * buf)
|
|||||||
res= heap_write(file,buf);
|
res= heap_write(file,buf);
|
||||||
if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
|
if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
|
||||||
file->s->records))
|
file->s->records))
|
||||||
update_key_stats();
|
key_stats_ok= FALSE;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +155,7 @@ int ha_heap::update_row(const byte * old_data, byte * new_data)
|
|||||||
res= heap_update(file,old_data,new_data);
|
res= heap_update(file,old_data,new_data);
|
||||||
if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
|
if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
|
||||||
file->s->records)
|
file->s->records)
|
||||||
update_key_stats();
|
key_stats_ok= FALSE;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +166,7 @@ int ha_heap::delete_row(const byte * buf)
|
|||||||
res= heap_delete(file,buf);
|
res= heap_delete(file,buf);
|
||||||
if (!res && table->s->tmp_table == NO_TMP_TABLE &&
|
if (!res && table->s->tmp_table == NO_TMP_TABLE &&
|
||||||
++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
|
++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
|
||||||
update_key_stats();
|
key_stats_ok= FALSE;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,6 +288,13 @@ void ha_heap::info(uint flag)
|
|||||||
delete_length= info.deleted * info.reclength;
|
delete_length= info.deleted * info.reclength;
|
||||||
if (flag & HA_STATUS_AUTO)
|
if (flag & HA_STATUS_AUTO)
|
||||||
auto_increment_value= info.auto_increment;
|
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)
|
int ha_heap::extra(enum ha_extra_function operation)
|
||||||
@ -289,7 +306,7 @@ int ha_heap::delete_all_rows()
|
|||||||
{
|
{
|
||||||
heap_clear(file);
|
heap_clear(file);
|
||||||
if (table->s->tmp_table == NO_TMP_TABLE)
|
if (table->s->tmp_table == NO_TMP_TABLE)
|
||||||
update_key_stats();
|
key_stats_ok= FALSE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,6 +465,9 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
|
|||||||
min_key->flag != HA_READ_KEY_EXACT ||
|
min_key->flag != HA_READ_KEY_EXACT ||
|
||||||
max_key->flag != HA_READ_AFTER_KEY)
|
max_key->flag != HA_READ_AFTER_KEY)
|
||||||
return HA_POS_ERROR; // Can only use exact keys
|
return HA_POS_ERROR; // Can only use exact keys
|
||||||
|
|
||||||
|
/* Assert that info() did run. We need current statistics here. */
|
||||||
|
DBUG_ASSERT(key_stats_ok);
|
||||||
return key->rec_per_key[key->key_parts-1];
|
return key->rec_per_key[key->key_parts-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +29,10 @@ class ha_heap: public handler
|
|||||||
key_map btree_keys;
|
key_map btree_keys;
|
||||||
/* number of records changed since last statistics update */
|
/* number of records changed since last statistics update */
|
||||||
uint records_changed;
|
uint records_changed;
|
||||||
|
bool key_stats_ok;
|
||||||
public:
|
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() {}
|
~ha_heap() {}
|
||||||
const char *table_type() const
|
const char *table_type() const
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user