diff options
author | Igor Babaev <igor@askmonty.org> | 2012-12-12 23:16:54 -0800 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-12-12 23:16:54 -0800 |
commit | 65820439bdafeead66496b489c076012c334c710 (patch) | |
tree | ba5134a5674e237eb510a6b10a1a7cac28ec9f26 /sql/sql_statistics.cc | |
parent | 109c104d07c6cce68ecae66c1a4dcdb83826954f (diff) | |
download | mariadb-git-65820439bdafeead66496b489c076012c334c710.tar.gz |
Fixed bug mdev-3891.
If a query referenced some system statistical tables, but not all of them,
then executing an ANALYZE command simultaneously with this query could
lead to a deadlock.
The fix prohibited reading statistics from system statistical tables
for such queries.
Removed the function unlock_tables_n_open_system_tables_for_write()
as not used anymore.
Performed some minor refactoring of the code in sql_statistics.cc.
Diffstat (limited to 'sql/sql_statistics.cc')
-rw-r--r-- | sql/sql_statistics.cc | 102 |
1 files changed, 62 insertions, 40 deletions
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 4becf5ab7ae..93d3a1c581f 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -127,6 +127,38 @@ inline void init_table_list_for_single_stat_table(TABLE_LIST *tbl, /** + @brief + Open all statistical tables and lock them +*/ + +static +inline int open_stat_tables(THD *thd, TABLE_LIST *tables, + Open_tables_backup *backup, + bool for_write) +{ + init_table_list_for_stat_tables(tables, for_write); + init_mdl_requests(tables); + return open_system_tables_for_read(thd, tables, backup); +} + + +/** + @brief + Open a statistical table and lock it +*/ +static +inline int open_single_stat_table(THD *thd, TABLE_LIST *table, + const LEX_STRING *stat_tab_name, + Open_tables_backup *backup, + bool for_write) +{ + init_table_list_for_single_stat_table(table, stat_tab_name, for_write); + init_mdl_requests(table); + return open_system_tables_for_read(thd, table, backup); +} + + +/** @details If the value of the parameter is_safe is TRUE then the function just copies the address pointed by the parameter src into the memory @@ -1199,7 +1231,7 @@ public: the number of distinct values for a column. The class employs the Unique class for this purpose. The class Count_distinct_field is used only by the function - collect_statistics_from_table to calculate the values for + collect_statistics_for_table to calculate the values for column avg_frequency of the statistical table column_stats. */ @@ -2179,12 +2211,9 @@ int update_statistics_for_table(THD *thd, TABLE *table) DBUG_ENTER("update_statistics_for_table"); - init_table_list_for_stat_tables(tables, TRUE); - init_mdl_requests(tables); + DEBUG_SYNC(thd, "statistics_update_start"); - if (unlock_tables_n_open_system_tables_for_write(thd, - tables, - &open_tables_backup)) + if (open_stat_tables(thd, tables, &open_tables_backup, TRUE)) { thd->clear_error(); DBUG_RETURN(rc); @@ -2266,7 +2295,7 @@ int update_statistics_for_table(THD *thd, TABLE *table) The parameter stat_tables should point to an array of TABLE_LIST objects for all statistical tables linked into a list. All statistical tables are supposed to be opened. - The function is called by read_statistics_for_table_if_needed(). + The function is called by read_statistics_for_tables_if_needed(). @retval 0 If data has been successfully read for the table @@ -2415,6 +2444,21 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables) return FALSE; } + /* + Do not read statistics for any query over non-user tables. + If the query references some statistical tables, but not all + of them, reading the statistics may lead to a deadlock + */ + for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) + { + if (!tl->is_view_or_derived() && tl->table) + { + TABLE_SHARE *table_share= tl->table->s; + if (table_share && table_share->table_category != TABLE_CATEGORY_USER) + return FALSE; + } + } + for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) { if (!tl->is_view_or_derived() && tl->table) @@ -2460,12 +2504,12 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) DBUG_ENTER("read_statistics_for_table_if_needed"); + DEBUG_SYNC(thd, "statistics_read_start"); + if (!statistics_for_tables_is_needed(thd, tables)) DBUG_RETURN(0); - init_table_list_for_stat_tables(stat_tables, FALSE); - init_mdl_requests(stat_tables); - if (open_system_tables_for_read(thd, stat_tables, &open_tables_backup)) + if (open_stat_tables(thd, stat_tables, &open_tables_backup, FALSE)) { thd->clear_error(); DBUG_RETURN(1); @@ -2527,12 +2571,7 @@ int delete_statistics_for_table(THD *thd, LEX_STRING *db, LEX_STRING *tab) DBUG_ENTER("delete_statistics_for_table"); - init_table_list_for_stat_tables(tables, TRUE); - init_mdl_requests(tables); - - if (open_system_tables_for_read(thd, - tables, - &open_tables_backup)) + if (open_stat_tables(thd, tables, &open_tables_backup, TRUE)) { thd->clear_error(); DBUG_RETURN(rc); @@ -2619,12 +2658,8 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col) DBUG_ENTER("delete_statistics_for_column"); - init_table_list_for_single_stat_table(&tables, &stat_table_name[1], TRUE); - init_mdl_requests(&tables); - - if (open_system_tables_for_read(thd, - &tables, - &open_tables_backup)) + if (open_single_stat_table(thd, &tables, &stat_table_name[1], + &open_tables_backup, TRUE)) { thd->clear_error(); DBUG_RETURN(rc); @@ -2692,12 +2727,8 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, DBUG_ENTER("delete_statistics_for_index"); - init_table_list_for_single_stat_table(&tables, &stat_table_name[2], TRUE); - init_mdl_requests(&tables); - - if (open_system_tables_for_read(thd, - &tables, - &open_tables_backup)) + if (open_single_stat_table(thd, &tables, &stat_table_name[2], + &open_tables_backup, TRUE)) { thd->clear_error(); DBUG_RETURN(rc); @@ -2779,12 +2810,7 @@ int rename_table_in_stat_tables(THD *thd, LEX_STRING *db, LEX_STRING *tab, DBUG_ENTER("rename_table_in_stat_tables"); - init_table_list_for_stat_tables(tables, TRUE); - init_mdl_requests(tables); - - if (open_system_tables_for_read(thd, - tables, - &open_tables_backup)) + if (open_stat_tables(thd, tables, &open_tables_backup, TRUE)) { thd->clear_error(); DBUG_RETURN(rc); @@ -2876,12 +2902,8 @@ int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col, DBUG_ENTER("rename_column_in_stat_tables"); - init_table_list_for_single_stat_table(&tables, &stat_table_name[1], TRUE); - init_mdl_requests(&tables); - - if (open_system_tables_for_read(thd, - &tables, - &open_tables_backup)) + if (open_single_stat_table(thd, &tables, &stat_table_name[1], + &open_tables_backup, TRUE)) { thd->clear_error(); DBUG_RETURN(rc); |