Commit 01dca17a authored by Igor Babaev's avatar Igor Babaev

Fixed bug mdev-3979.

Made allocation of memory for statistical data in a table share to be thread safe.
This memory is now allocated in a special MEM_ROOT that is created for each
table share.  
parent e44253a1
...@@ -3143,16 +3143,6 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, ...@@ -3143,16 +3143,6 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
while (table_cache_count > table_cache_size && unused_tables) while (table_cache_count > table_cache_size && unused_tables)
free_cache_entry(unused_tables); free_cache_entry(unused_tables);
if (get_use_stat_tables_mode(thd) > NEVER)
{
if (share->table_category != TABLE_CATEGORY_SYSTEM)
{
if (!share->stats_can_be_read &&
!alloc_statistics_for_table_share(thd, share, TRUE))
share->stats_can_be_read= TRUE;
}
}
mysql_mutex_unlock(&LOCK_open); mysql_mutex_unlock(&LOCK_open);
/* make a new table */ /* make a new table */
...@@ -4638,22 +4628,24 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, ...@@ -4638,22 +4628,24 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
if (get_use_stat_tables_mode(thd) > NEVER && tables->table) if (get_use_stat_tables_mode(thd) > NEVER && tables->table)
{ {
TABLE_SHARE *table_share= tables->table->s; TABLE_SHARE *table_share= tables->table->s;
if (table_share && table_share->table_category != TABLE_CATEGORY_SYSTEM) if (table_share && table_share->table_category == TABLE_CATEGORY_USER &&
{ table_share->tmp_table == NO_TMP_TABLE)
if (!table_share->stats_can_be_read && {
!alloc_statistics_for_table_share(thd, table_share, FALSE)) if (table_share->stats_cb.stats_can_be_read ||
{ !alloc_statistics_for_table_share(thd, table_share, FALSE))
KEY *key_info= table_share->key_info; {
KEY *key_info_end= key_info + table_share->keys; if (table_share->stats_cb.stats_can_be_read)
KEY *table_key_info= tables->table->key_info; {
for ( ; key_info < key_info_end; key_info++, table_key_info++) KEY *key_info= table_share->key_info;
table_key_info->read_stats= key_info->read_stats; KEY *key_info_end= key_info + table_share->keys;
Field **field_ptr= table_share->field; KEY *table_key_info= tables->table->key_info;
Field **table_field_ptr= tables->table->field; for ( ; key_info < key_info_end; key_info++, table_key_info++)
for ( ; *field_ptr; field_ptr++, table_field_ptr++) table_key_info->read_stats= key_info->read_stats;
(*table_field_ptr)->read_stats= (*field_ptr)->read_stats; Field **field_ptr= table_share->field;
Field **table_field_ptr= tables->table->field;
table_share->stats_can_be_read= TRUE; for ( ; *field_ptr; field_ptr++, table_field_ptr++)
(*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
}
} }
} }
} }
...@@ -4895,7 +4887,7 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags, ...@@ -4895,7 +4887,7 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
} }
/* /*
Initialize temporary MEM_ROOT for new .FRM parsing. Do not allocate Initialize temporary MEM_ROOT for new .FRM parsing. Do not alloctaate
anything yet, to avoid penalty for statements which don't use views anything yet, to avoid penalty for statements which don't use views
and thus new .FRM format. and thus new .FRM format.
*/ */
......
This diff is collapsed.
...@@ -102,6 +102,7 @@ class Table_statistics ...@@ -102,6 +102,7 @@ class Table_statistics
public: public:
my_bool cardinality_is_null; /* TRUE if the cardinality is unknown */ my_bool cardinality_is_null; /* TRUE if the cardinality is unknown */
ha_rows cardinality; /* Number of rows in the table */ ha_rows cardinality; /* Number of rows in the table */
uchar *min_max_record_buffers; /* Record buffers for min/max values */
Column_statistics *column_stats; /* Array of statistical data for columns */ Column_statistics *column_stats; /* Array of statistical data for columns */
Index_statistics *index_stats; /* Array of statistical data for indexes */ Index_statistics *index_stats; /* Array of statistical data for indexes */
ulong *idx_avg_frequency; /* Array of records per key for index prefixes */ ulong *idx_avg_frequency; /* Array of records per key for index prefixes */
......
...@@ -340,6 +340,8 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, ...@@ -340,6 +340,8 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key,
share->free_tables.empty(); share->free_tables.empty();
share->m_flush_tickets.empty(); share->m_flush_tickets.empty();
init_sql_alloc(&share->stats_cb.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root)); memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root));
mysql_mutex_init(key_TABLE_SHARE_LOCK_ha_data, mysql_mutex_init(key_TABLE_SHARE_LOCK_ha_data,
&share->LOCK_ha_data, MY_MUTEX_INIT_FAST); &share->LOCK_ha_data, MY_MUTEX_INIT_FAST);
...@@ -420,6 +422,14 @@ void TABLE_SHARE::destroy() ...@@ -420,6 +422,14 @@ void TABLE_SHARE::destroy()
uint idx; uint idx;
KEY *info_it; KEY *info_it;
if (tmp_table == NO_TMP_TABLE)
mysql_mutex_lock(&LOCK_ha_data);
free_root(&stats_cb.mem_root, MYF(0));
stats_cb.stats_can_be_read= FALSE;
stats_cb.stats_is_read= FALSE;
if (tmp_table == NO_TMP_TABLE)
mysql_mutex_unlock(&LOCK_ha_data);
/* The mutex is initialized only for shares that are part of the TDC */ /* The mutex is initialized only for shares that are part of the TDC */
if (tmp_table == NO_TMP_TABLE) if (tmp_table == NO_TMP_TABLE)
mysql_mutex_destroy(&LOCK_ha_data); mysql_mutex_destroy(&LOCK_ha_data);
......
...@@ -547,6 +547,21 @@ typedef I_P_List <Wait_for_flush, ...@@ -547,6 +547,21 @@ typedef I_P_List <Wait_for_flush,
Wait_for_flush_list; Wait_for_flush_list;
/**
Control block to access table statistics loaded
from persistent statistical tables
*/
struct TABLE_STATISTICS_CB
{
MEM_ROOT mem_root; /* MEM_ROOT to allocate statistical data for the table */
Table_statistics *table_stats; /* Structure to access the statistical data */
bool stats_can_be_read; /* Memory for statistical data is allocated */
bool stats_is_read; /* Statistical data for table has been read
from statistical tables */
};
/** /**
This structure is shared between different table objects. There is one This structure is shared between different table objects. There is one
instance of table share per one table in the database. instance of table share per one table in the database.
...@@ -585,14 +600,7 @@ struct TABLE_SHARE ...@@ -585,14 +600,7 @@ struct TABLE_SHARE
KEY *key_info; /* data of keys in database */ KEY *key_info; /* data of keys in database */
uint *blob_field; /* Index to blobs in Field arrray*/ uint *blob_field; /* Index to blobs in Field arrray*/
bool stats_can_be_read; /* Memory for statistical data is allocated */ TABLE_STATISTICS_CB stats_cb;
bool stats_is_read; /* Statistical data for table has been read
from statistical tables */
/*
This structure is used for statistical data on the table
that has been read from the statistical table table_stat
*/
Table_statistics *read_stats;
uchar *default_values; /* row with default values */ uchar *default_values; /* row with default values */
LEX_STRING comment; /* Comment about table */ LEX_STRING comment; /* Comment about table */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment