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,
while (table_cache_count > table_cache_size && 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);
/* make a new table */
......@@ -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)
{
TABLE_SHARE *table_share= tables->table->s;
if (table_share && table_share->table_category != TABLE_CATEGORY_SYSTEM)
{
if (!table_share->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;
KEY *table_key_info= tables->table->key_info;
for ( ; key_info < key_info_end; key_info++, table_key_info++)
table_key_info->read_stats= key_info->read_stats;
Field **field_ptr= table_share->field;
Field **table_field_ptr= tables->table->field;
for ( ; *field_ptr; field_ptr++, table_field_ptr++)
(*table_field_ptr)->read_stats= (*field_ptr)->read_stats;
table_share->stats_can_be_read= TRUE;
if (table_share && table_share->table_category == TABLE_CATEGORY_USER &&
table_share->tmp_table == NO_TMP_TABLE)
{
if (table_share->stats_cb.stats_can_be_read ||
!alloc_statistics_for_table_share(thd, table_share, FALSE))
{
if (table_share->stats_cb.stats_can_be_read)
{
KEY *key_info= table_share->key_info;
KEY *key_info_end= key_info + table_share->keys;
KEY *table_key_info= tables->table->key_info;
for ( ; key_info < key_info_end; key_info++, table_key_info++)
table_key_info->read_stats= key_info->read_stats;
Field **field_ptr= table_share->field;
Field **table_field_ptr= tables->table->field;
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,
}
/*
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
and thus new .FRM format.
*/
......
This diff is collapsed.
......@@ -102,6 +102,7 @@ class Table_statistics
public:
my_bool cardinality_is_null; /* TRUE if the cardinality is unknown */
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 */
Index_statistics *index_stats; /* Array of statistical data for indexes */
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,
share->free_tables.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));
mysql_mutex_init(key_TABLE_SHARE_LOCK_ha_data,
&share->LOCK_ha_data, MY_MUTEX_INIT_FAST);
......@@ -420,6 +422,14 @@ void TABLE_SHARE::destroy()
uint idx;
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 */
if (tmp_table == NO_TMP_TABLE)
mysql_mutex_destroy(&LOCK_ha_data);
......
......@@ -547,6 +547,21 @@ typedef I_P_List <Wait_for_flush,
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
instance of table share per one table in the database.
......@@ -585,14 +600,7 @@ struct TABLE_SHARE
KEY *key_info; /* data of keys in database */
uint *blob_field; /* Index to blobs in Field arrray*/
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 used for statistical data on the table
that has been read from the statistical table table_stat
*/
Table_statistics *read_stats;
TABLE_STATISTICS_CB stats_cb;
uchar *default_values; /* row with default values */
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