Fixed bug mdev-504.
Opening system statistical tables and reading statistical data from them for a regular table should be done after opening and locking this regular table. No test case is provided with this patch.
This commit is contained in:
parent
cfde11fc4f
commit
b3f09e8aa0
@ -40,7 +40,7 @@ select * from mysql.index_stat;
|
|||||||
# assumes that start the code of memory allocation for stats data has this line:
|
# assumes that start the code of memory allocation for stats data has this line:
|
||||||
#
|
#
|
||||||
# DEBUG_SYNC(thd, "statistics_mem_alloc_start1");
|
# DEBUG_SYNC(thd, "statistics_mem_alloc_start1");
|
||||||
# DEBUG_SYNC(thd, "statistics_mem_alloc-start2");
|
# DEBUG_SYNC(thd, "statistics_mem_alloc_start2");
|
||||||
#
|
#
|
||||||
|
|
||||||
let $Q6=
|
let $Q6=
|
||||||
|
@ -4666,12 +4666,6 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
|||||||
|
|
||||||
table_share->stats_can_be_read= TRUE;
|
table_share->stats_can_be_read= TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table_share->stats_can_be_read && !table_share->stats_is_read)
|
|
||||||
{
|
|
||||||
(void) read_statistics_for_table(thd, tables->table);
|
|
||||||
table_share->stats_is_read= TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5615,6 +5609,8 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
|
|||||||
if (lock_tables(thd, tables, counter, flags))
|
if (lock_tables(thd, tables, counter, flags))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
(void) read_statistics_for_tables_if_needed(thd, tables);
|
||||||
|
|
||||||
if (derived)
|
if (derived)
|
||||||
{
|
{
|
||||||
if (mysql_handle_derived(thd->lex, DT_INIT))
|
if (mysql_handle_derived(thd->lex, DT_INIT))
|
||||||
|
@ -312,7 +312,7 @@ int dynamic_column_error_message(enum_dyncol_func_result rc);
|
|||||||
/* open_and_lock_tables with optional derived handling */
|
/* open_and_lock_tables with optional derived handling */
|
||||||
int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived);
|
int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived);
|
||||||
|
|
||||||
int read_statistics_for_table(THD *thd, TABLE *table);
|
int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables);
|
||||||
int collect_statistics_for_table(THD *thd, TABLE *table);
|
int collect_statistics_for_table(THD *thd, TABLE *table);
|
||||||
int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *share,
|
int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *share,
|
||||||
bool is_safe);
|
bool is_safe);
|
||||||
|
@ -1726,7 +1726,7 @@ int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share,
|
|||||||
Field **field_ptr;
|
Field **field_ptr;
|
||||||
uint cnt= 0;
|
uint cnt= 0;
|
||||||
|
|
||||||
DBUG_ENTER("alloc_statistics_for_table");
|
DBUG_ENTER("alloc_statistics_for_table_share");
|
||||||
|
|
||||||
DEBUG_SYNC(thd, "statistics_mem_alloc_start1");
|
DEBUG_SYNC(thd, "statistics_mem_alloc_start1");
|
||||||
DEBUG_SYNC(thd, "statistics_mem_alloc_start2");
|
DEBUG_SYNC(thd, "statistics_mem_alloc_start2");
|
||||||
@ -2245,6 +2245,8 @@ int update_statistics_for_table(THD *thd, TABLE *table)
|
|||||||
thd The thread handle
|
thd The thread handle
|
||||||
@param
|
@param
|
||||||
table The table to read statistics on
|
table The table to read statistics on
|
||||||
|
@param
|
||||||
|
stat_tables The array of TABLE_LIST objects for statistical tables
|
||||||
|
|
||||||
@details
|
@details
|
||||||
For each statistical table the function looks for the rows from this
|
For each statistical table the function looks for the rows from this
|
||||||
@ -2252,54 +2254,42 @@ int update_statistics_for_table(THD *thd, TABLE *table)
|
|||||||
the data from statistical columns of it is read into the appropriate
|
the data from statistical columns of it is read into the appropriate
|
||||||
fields of internal structures for 'table'. Later at the query processing
|
fields of internal structures for 'table'. Later at the query processing
|
||||||
this data are supposed to be used by the optimizer.
|
this data are supposed to be used by the optimizer.
|
||||||
The function is called in function open_tables.
|
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().
|
||||||
|
|
||||||
@retval
|
@retval
|
||||||
0 If data has been successfully read from all statistical tables
|
0 If data has been successfully read for the table
|
||||||
@retval
|
@retval
|
||||||
1 Otherwise
|
1 Otherwise
|
||||||
|
|
||||||
@note
|
@note
|
||||||
The function first calls the function open_system_tables_for_read to
|
Objects of the helper classes Table_stat, Column_stat and Index_stat
|
||||||
be able to read info from the statistical tables. On success the data is
|
|
||||||
read from one table after another after which the statistical tables are
|
|
||||||
closed. Objects of the helper classes Table_stat, Column_stat and Index_stat
|
|
||||||
are employed to read statistical data from the statistical tables.
|
are employed to read statistical data from the statistical tables.
|
||||||
TODO. Consider a variant when statistical tables are opened and closed
|
|
||||||
only once for all tables, not for every table of the query as it's done
|
|
||||||
now.
|
now.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int read_statistics_for_table(THD *thd, TABLE *table)
|
static
|
||||||
|
int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
TABLE *stat_table;
|
TABLE *stat_table;
|
||||||
Field *table_field;
|
Field *table_field;
|
||||||
Field **field_ptr;
|
Field **field_ptr;
|
||||||
KEY *key_info, *key_info_end;
|
KEY *key_info, *key_info_end;
|
||||||
TABLE_LIST tables[STATISTICS_TABLES];
|
|
||||||
Open_tables_backup open_tables_backup;
|
|
||||||
TABLE_SHARE *table_share= table->s;
|
TABLE_SHARE *table_share= table->s;
|
||||||
|
|
||||||
DBUG_ENTER("read_statistics_for_table");
|
DBUG_ENTER("read_statistics_for_table");
|
||||||
|
|
||||||
init_table_list_for_stat_tables(tables, FALSE);
|
|
||||||
init_mdl_requests(tables);
|
|
||||||
|
|
||||||
if (open_system_tables_for_read(thd, tables, &open_tables_backup))
|
|
||||||
{
|
|
||||||
thd->clear_error();
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read statistics from the statistical table table_stat */
|
/* Read statistics from the statistical table table_stat */
|
||||||
stat_table= tables[TABLE_STAT].table;
|
stat_table= stat_tables[TABLE_STAT].table;
|
||||||
Table_stat table_stat(stat_table, table);
|
Table_stat table_stat(stat_table, table);
|
||||||
table_stat.set_key_fields();
|
table_stat.set_key_fields();
|
||||||
table_stat.get_stat_values();
|
table_stat.get_stat_values();
|
||||||
|
|
||||||
/* Read statistics from the statistical table column_stat */
|
/* Read statistics from the statistical table column_stat */
|
||||||
stat_table= tables[COLUMN_STAT].table;
|
stat_table= stat_tables[COLUMN_STAT].table;
|
||||||
Column_stat column_stat(stat_table, table);
|
Column_stat column_stat(stat_table, table);
|
||||||
for (field_ptr= table_share->field; *field_ptr; field_ptr++)
|
for (field_ptr= table_share->field; *field_ptr; field_ptr++)
|
||||||
{
|
{
|
||||||
@ -2309,7 +2299,7 @@ int read_statistics_for_table(THD *thd, TABLE *table)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read statistics from the statistical table index_stat */
|
/* Read statistics from the statistical table index_stat */
|
||||||
stat_table= tables[INDEX_STAT].table;
|
stat_table= stat_tables[INDEX_STAT].table;
|
||||||
Index_stat index_stat(stat_table, table);
|
Index_stat index_stat(stat_table, table);
|
||||||
for (key_info= table_share->key_info,
|
for (key_info= table_share->key_info,
|
||||||
key_info_end= key_info + table_share->keys;
|
key_info_end= key_info + table_share->keys;
|
||||||
@ -2369,6 +2359,124 @@ int read_statistics_for_table(THD *thd, TABLE *table)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Check whether any statistics is to be read for tables from a table list
|
||||||
|
|
||||||
|
@param
|
||||||
|
thd The thread handle
|
||||||
|
@param
|
||||||
|
tables The tables list for whose tables the check is to be done
|
||||||
|
|
||||||
|
@details
|
||||||
|
The function checks whether for any of the tables opened and locked for
|
||||||
|
a statement statistics from statistical tables is needed to be read.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
TRUE statistics for any of the tables is needed to be read
|
||||||
|
@retval
|
||||||
|
FALSE Otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
static
|
||||||
|
bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
|
||||||
|
{
|
||||||
|
if (thd->bootstrap || thd->variables.use_stat_tables == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!tables)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
switch(thd->lex->sql_command) {
|
||||||
|
case SQLCOM_SELECT:
|
||||||
|
case SQLCOM_INSERT:
|
||||||
|
case SQLCOM_INSERT_SELECT:
|
||||||
|
case SQLCOM_UPDATE:
|
||||||
|
case SQLCOM_UPDATE_MULTI:
|
||||||
|
case SQLCOM_DELETE:
|
||||||
|
case SQLCOM_DELETE_MULTI:
|
||||||
|
case SQLCOM_REPLACE:
|
||||||
|
case SQLCOM_REPLACE_SELECT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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->stats_can_be_read &&
|
||||||
|
!table_share->stats_is_read)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief
|
||||||
|
Read statistics for tables from a table list if it is needed
|
||||||
|
|
||||||
|
@param
|
||||||
|
thd The thread handle
|
||||||
|
@param
|
||||||
|
tables The tables list for whose tables to read statistics
|
||||||
|
|
||||||
|
@details
|
||||||
|
The function first checks whether for any of the tables opened and locked
|
||||||
|
for a statement statistics from statistical tables is needed to be read.
|
||||||
|
Then, if so, it opens system statistical tables for read and reads
|
||||||
|
the statistical data from them for those tables from the list for which it
|
||||||
|
makes sense. Then the function closes system statistical tables.
|
||||||
|
|
||||||
|
@retval
|
||||||
|
0 Statistics for tables was successfully read
|
||||||
|
@retval
|
||||||
|
1 Otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
|
||||||
|
{
|
||||||
|
TABLE_LIST stat_tables[STATISTICS_TABLES];
|
||||||
|
Open_tables_backup open_tables_backup;
|
||||||
|
|
||||||
|
DBUG_ENTER("read_statistics_for_table_if_needed");
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
thd->clear_error();
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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->stats_can_be_read &&
|
||||||
|
!table_share->stats_is_read)
|
||||||
|
{
|
||||||
|
(void) read_statistics_for_table(thd, tl->table, stat_tables);
|
||||||
|
table_share->stats_is_read= TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
close_system_tables(thd, &open_tables_backup);
|
close_system_tables(thd, &open_tables_backup);
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user