mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-31957 Concurrent ALTER and ANALYZE collecting statistics can result in stale statistical data
Example of what causes the problem: T1: ANALYZE TABLE starts to collect statistics T2: ALTER TABLE starts by deleting statistics for all changed fields, then creates a temp table and copies data to it. T1: ANALYZE ends and writes to the statistics tables. T2: ALTER TABLE renames temp table in place of the old table. Now the statistics from analyze matches the old deleted tables. Fixed by waiting to delete old statistics until ALTER TABLE is the only one using the old table and ensure that rename of columns can handle swapping of column names. rename_columns_in_stat_table() (former rename_column_in_stat_tables()) now takes a list of columns to rename. It uses the following algorithm to update column_stats to be able to handle circular renames - While there are columns to be renamed and it is the first loop or last rename loop did change something. - Loop over all columns to be renamed - Change column name in column_stat - If fail because of duplicate key - If this is first change attempt for this column - Change column name to a temporary column name - If there was a conflicting row, replace it with the current row. else - Remove entry from column list - Loop over all remaining columns in the list - Remove the conflicting row - Change column from temporary name to final name in column_stat Other things: - Don't flush tables for every operation. Only flush when all updates are done. - Rename of columns was not handled in case of ALGORITHM=copy (old bug). - Fixed that we do not collect statistics for hidden hash columns used by UNIQUE constraint on long values. - Fixed that we do not collect statistics for blob columns referred by generated virtual columns. This was achieved by storing the fields for which we want to have statistics in table->has_value_set instead of in table->read_set. - Rename of indexes was not handled for persistent statistics. - This is now handled similar as rename of columns. Renamed columns are now stored in 'rename_stat_indexes' and handled in Alter_info::delete_statistics() together with drooped indexes. - ALTER TABLE .. ADD INDEX may instead of creating a new index rename an existing generated foreign key index. This was not reflected in the index_stats table because this was handled in mysql_prepare_create_table instead instead of in the mysql_alter() code. Fixed by adding a call in mysql_prepare_create_table() to drop the changed index. I also had to change the code that 'marked the index' to be ignored with code that would not destroy the original index name. Reviewer: Sergei Petrunia <sergey@mariadb.com>
This commit is contained in:
@@ -119,16 +119,21 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables);
|
||||
int read_statistics_for_tables(THD *thd, TABLE_LIST *tables,
|
||||
bool force_reload);
|
||||
int collect_statistics_for_table(THD *thd, TABLE *table);
|
||||
int alloc_statistics_for_table(THD *thd, TABLE *table);
|
||||
int alloc_statistics_for_table(THD *thd, TABLE *table, MY_BITMAP *stat_fields);
|
||||
int update_statistics_for_table(THD *thd, TABLE *table);
|
||||
int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab);
|
||||
int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db,
|
||||
const LEX_CSTRING *tab);
|
||||
int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col);
|
||||
int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info,
|
||||
bool ext_prefixes_only);
|
||||
int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab,
|
||||
const LEX_CSTRING *new_db, const LEX_CSTRING *new_tab);
|
||||
int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col,
|
||||
const char *new_name);
|
||||
int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db,
|
||||
const LEX_CSTRING *tab,
|
||||
const LEX_CSTRING *new_db,
|
||||
const LEX_CSTRING *new_tab);
|
||||
int rename_columns_in_stat_table(THD *thd, TABLE *tab,
|
||||
List<Alter_info::RENAME_COLUMN_STAT_PARAMS> *fields);
|
||||
int rename_indexes_in_stat_table(THD *thd, TABLE *tab,
|
||||
List<Alter_info::RENAME_INDEX_STAT_PARAMS> *indexes);
|
||||
void set_statistics_for_table(THD *thd, TABLE *table);
|
||||
|
||||
double get_column_avg_frequency(Field * field);
|
||||
|
Reference in New Issue
Block a user