Fixed bug mdev-4019.
The bug could cause a crash when several connections needed persistent statistics for the same table. Also added a missing call of set_statistics_for_table() in the code of the function mysql_update.
This commit is contained in:
parent
7d9df8075e
commit
7d5c56cb41
@ -219,4 +219,24 @@ set debug_sync='RESET';
|
|||||||
set global use_stat_tables=@save_global_use_stat_tables;
|
set global use_stat_tables=@save_global_use_stat_tables;
|
||||||
DROP DATABASE dbt3_s001;
|
DROP DATABASE dbt3_s001;
|
||||||
use test;
|
use test;
|
||||||
|
set @save_global_use_stat_tables=@@global.use_stat_tables;
|
||||||
|
set global use_stat_tables='preferably';
|
||||||
|
set debug_sync='RESET';
|
||||||
|
create table t1 (a int, b int, key(a));
|
||||||
|
insert t1 values (1,1),(2,2);
|
||||||
|
analyze table t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 analyze status OK
|
||||||
|
SET debug_sync='after_open_table_ignore_flush WAIT_FOR go';
|
||||||
|
select * from information_schema.statistics where table_schema='test';
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
SET DEBUG_SYNC= "now SIGNAL go";
|
||||||
|
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT INDEX_COMMENT
|
||||||
|
def test t1 1 test a 1 a A 2 NULL NULL YES BTREE
|
||||||
|
set debug_sync='RESET';
|
||||||
|
drop table t1;
|
||||||
|
set global use_stat_tables=@save_global_use_stat_tables;
|
||||||
set use_stat_tables=@save_use_stat_tables;
|
set use_stat_tables=@save_use_stat_tables;
|
||||||
|
@ -228,6 +228,26 @@ set debug_sync='RESET';
|
|||||||
set global use_stat_tables=@save_global_use_stat_tables;
|
set global use_stat_tables=@save_global_use_stat_tables;
|
||||||
DROP DATABASE dbt3_s001;
|
DROP DATABASE dbt3_s001;
|
||||||
use test;
|
use test;
|
||||||
|
set @save_global_use_stat_tables=@@global.use_stat_tables;
|
||||||
|
set global use_stat_tables='preferably';
|
||||||
|
set debug_sync='RESET';
|
||||||
|
create table t1 (a int, b int, key(a));
|
||||||
|
insert t1 values (1,1),(2,2);
|
||||||
|
analyze table t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 analyze status OK
|
||||||
|
SET debug_sync='after_open_table_ignore_flush WAIT_FOR go';
|
||||||
|
select * from information_schema.statistics where table_schema='test';
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
SET DEBUG_SYNC= "now SIGNAL go";
|
||||||
|
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT INDEX_COMMENT
|
||||||
|
def test t1 1 test a 1 a A 2 NULL NULL YES BTREE
|
||||||
|
set debug_sync='RESET';
|
||||||
|
drop table t1;
|
||||||
|
set global use_stat_tables=@save_global_use_stat_tables;
|
||||||
set use_stat_tables=@save_use_stat_tables;
|
set use_stat_tables=@save_use_stat_tables;
|
||||||
set optimizer_switch=@save_optimizer_switch_for_stat_tables_test;
|
set optimizer_switch=@save_optimizer_switch_for_stat_tables_test;
|
||||||
SET SESSION STORAGE_ENGINE=DEFAULT;
|
SET SESSION STORAGE_ENGINE=DEFAULT;
|
||||||
|
@ -242,4 +242,37 @@ DROP DATABASE dbt3_s001;
|
|||||||
|
|
||||||
use test;
|
use test;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug mdev-4019: crash when executing in parallel ANALYZE and
|
||||||
|
# SELECT * FROM information_schema.statistics
|
||||||
|
#
|
||||||
|
|
||||||
|
set @save_global_use_stat_tables=@@global.use_stat_tables;
|
||||||
|
set global use_stat_tables='preferably';
|
||||||
|
set debug_sync='RESET';
|
||||||
|
|
||||||
|
create table t1 (a int, b int, key(a));
|
||||||
|
insert t1 values (1,1),(2,2);
|
||||||
|
|
||||||
|
analyze table t1;
|
||||||
|
|
||||||
|
SET debug_sync='after_open_table_ignore_flush WAIT_FOR go';
|
||||||
|
send select * from information_schema.statistics where table_schema='test';
|
||||||
|
|
||||||
|
connect(con1, localhost, root);
|
||||||
|
connection con1;
|
||||||
|
select * from t1;
|
||||||
|
SET DEBUG_SYNC= "now SIGNAL go";
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
disconnect con1;
|
||||||
|
set debug_sync='RESET';
|
||||||
|
|
||||||
|
drop table t1;
|
||||||
|
set global use_stat_tables=@save_global_use_stat_tables;
|
||||||
|
|
||||||
|
|
||||||
set use_stat_tables=@save_use_stat_tables;
|
set use_stat_tables=@save_use_stat_tables;
|
||||||
|
@ -4654,6 +4654,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
|||||||
Field **table_field_ptr= tables->table->field;
|
Field **table_field_ptr= tables->table->field;
|
||||||
for ( ; *field_ptr; field_ptr++, table_field_ptr++)
|
for ( ; *field_ptr; field_ptr++, table_field_ptr++)
|
||||||
(*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
|
(*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
|
||||||
|
tables->table->stats_is_read= table_share->stats_cb.stats_is_read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2501,6 +2501,8 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table->stats_is_read= TRUE;
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2559,6 +2561,8 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
|
|||||||
table_share->stats_cb.stats_can_be_read &&
|
table_share->stats_cb.stats_can_be_read &&
|
||||||
!table_share->stats_cb.stats_is_read)
|
!table_share->stats_cb.stats_is_read)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
if (table_share->stats_cb.stats_is_read)
|
||||||
|
tl->table->stats_is_read= TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2618,6 +2622,8 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
|
|||||||
(void) read_statistics_for_table(thd, tl->table, stat_tables);
|
(void) read_statistics_for_table(thd, tl->table, stat_tables);
|
||||||
table_share->stats_cb.stats_is_read= TRUE;
|
table_share->stats_cb.stats_is_read= TRUE;
|
||||||
}
|
}
|
||||||
|
if (table_share->stats_cb.stats_is_read)
|
||||||
|
tl->table->stats_is_read= TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3045,7 +3051,7 @@ void set_statistics_for_table(THD *thd, TABLE *table)
|
|||||||
Use_stat_tables_mode use_stat_table_mode= get_use_stat_tables_mode(thd);
|
Use_stat_tables_mode use_stat_table_mode= get_use_stat_tables_mode(thd);
|
||||||
table->used_stat_records=
|
table->used_stat_records=
|
||||||
(use_stat_table_mode <= COMPLEMENTARY ||
|
(use_stat_table_mode <= COMPLEMENTARY ||
|
||||||
!stats_cb->stats_is_read || read_stats->cardinality_is_null) ?
|
!table->stats_is_read || read_stats->cardinality_is_null) ?
|
||||||
table->file->stats.records : read_stats->cardinality;
|
table->file->stats.records : read_stats->cardinality;
|
||||||
KEY *key_info, *key_info_end;
|
KEY *key_info, *key_info_end;
|
||||||
for (key_info= table->key_info, key_info_end= key_info+table->s->keys;
|
for (key_info= table->key_info, key_info_end= key_info+table->s->keys;
|
||||||
@ -3053,7 +3059,7 @@ void set_statistics_for_table(THD *thd, TABLE *table)
|
|||||||
{
|
{
|
||||||
key_info->is_statistics_from_stat_tables=
|
key_info->is_statistics_from_stat_tables=
|
||||||
(use_stat_table_mode > COMPLEMENTARY &&
|
(use_stat_table_mode > COMPLEMENTARY &&
|
||||||
stats_cb->stats_is_read &&
|
table->stats_is_read &&
|
||||||
key_info->read_stats->avg_frequency_is_inited() &&
|
key_info->read_stats->avg_frequency_is_inited() &&
|
||||||
key_info->read_stats->get_avg_frequency(0) > 0.5);
|
key_info->read_stats->get_avg_frequency(0) > 0.5);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "sql_view.h" // check_key_in_view
|
#include "sql_view.h" // check_key_in_view
|
||||||
#include "sp_head.h"
|
#include "sp_head.h"
|
||||||
#include "sql_trigger.h"
|
#include "sql_trigger.h"
|
||||||
|
#include "sql_statistics.h"
|
||||||
#include "probes_mysql.h"
|
#include "probes_mysql.h"
|
||||||
#include "debug_sync.h"
|
#include "debug_sync.h"
|
||||||
#include "key.h" // is_key_used
|
#include "key.h" // is_key_used
|
||||||
@ -404,6 +405,7 @@ int mysql_update(THD *thd,
|
|||||||
#endif
|
#endif
|
||||||
/* Update the table->file->stats.records number */
|
/* Update the table->file->stats.records number */
|
||||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||||
|
set_statistics_for_table(thd, table);
|
||||||
|
|
||||||
select= make_select(table, 0, 0, conds, 0, &error);
|
select= make_select(table, 0, 0, conds, 0, &error);
|
||||||
if (error || !limit || thd->is_error() ||
|
if (error || !limit || thd->is_error() ||
|
||||||
|
@ -1189,6 +1189,7 @@ public:
|
|||||||
bool no_partitions_used; /* If true, all partitions have been pruned away */
|
bool no_partitions_used; /* If true, all partitions have been pruned away */
|
||||||
#endif
|
#endif
|
||||||
uint max_keys; /* Size of allocated key_info array. */
|
uint max_keys; /* Size of allocated key_info array. */
|
||||||
|
bool stats_is_read; /* Persistent statistics is read for the table */
|
||||||
MDL_ticket *mdl_ticket;
|
MDL_ticket *mdl_ticket;
|
||||||
|
|
||||||
void init(THD *thd, TABLE_LIST *tl);
|
void init(THD *thd, TABLE_LIST *tl);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user