Commit a93b3778 authored by Sergei Petrunia's avatar Sergei Petrunia

Fix histogram memory management

There are "local" histograms that are allocated by one thread for
one TABLE object, and "global" that are allocated for TABLE_SHARE.
parent 032587e2
...@@ -1045,6 +1045,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1045,6 +1045,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
else else
compl_result_code= HA_ADMIN_FAILED; compl_result_code= HA_ADMIN_FAILED;
free_statistics_for_table(thd, table->table);
if (compl_result_code) if (compl_result_code)
result_code= HA_ADMIN_FAILED; result_code= HA_ADMIN_FAILED;
else else
......
...@@ -63,7 +63,8 @@ ...@@ -63,7 +63,8 @@
equal to "never". equal to "never".
*/ */
Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type); Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type,
THD *owner);
/* Currently there are only 3 persistent statistical tables */ /* Currently there are only 3 persistent statistical tables */
static const uint STATISTICS_TABLES= 3; static const uint STATISTICS_TABLES= 3;
...@@ -1222,15 +1223,16 @@ class Column_stat: public Stat_table ...@@ -1222,15 +1223,16 @@ class Column_stat: public Stat_table
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
String val(buff, sizeof(buff), &my_charset_bin); String val(buff, sizeof(buff), &my_charset_bin);
uint fldno= COLUMN_STAT_HISTOGRAM; uint fldno= COLUMN_STAT_HISTOGRAM;
Histogram_base *hist;
Field *stat_field= stat_table->field[fldno]; Field *stat_field= stat_table->field[fldno];
table_field->read_stats->set_not_null(fldno); table_field->read_stats->set_not_null(fldno);
stat_field->val_str(&val); stat_field->val_str(&val);
hist= create_histogram(mem_root, table_field->read_stats->histogram_type_on_disk); Histogram_type hist_type=
if (!hist) table_field->read_stats->histogram_type_on_disk;
Histogram_base *hist;
if (!(hist= create_histogram(mem_root, hist_type, NULL)))
return NULL; return NULL;
if (!hist->parse(mem_root, table_field, if (!hist->parse(mem_root, table_field, hist_type,
table_field->read_stats->histogram_type_on_disk,
val.ptr(), val.length())) val.ptr(), val.length()))
{ {
table_field->read_stats->histogram_= hist; table_field->read_stats->histogram_= hist;
...@@ -2085,18 +2087,25 @@ class Histogram_builder_json : public Histogram_builder ...@@ -2085,18 +2087,25 @@ class Histogram_builder_json : public Histogram_builder
}; };
Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type) Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type,
THD *owner)
{ {
Histogram_base *res= NULL;
switch (hist_type) { switch (hist_type) {
case SINGLE_PREC_HB: case SINGLE_PREC_HB:
case DOUBLE_PREC_HB: case DOUBLE_PREC_HB:
return new (mem_root) Histogram_binary(); res= new (mem_root) Histogram_binary();
break;
case JSON_HB: case JSON_HB:
return new (mem_root) Histogram_json(); res= new (mem_root) Histogram_json();
break;
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
return NULL;
if (res)
res->set_owner(owner);
return res;
} }
...@@ -2691,6 +2700,25 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) ...@@ -2691,6 +2700,25 @@ int alloc_statistics_for_table(THD* thd, TABLE *table)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*
Free the "local" statistics for table.
We only free the statistics that is not on MEM_ROOT and needs to be
explicitly freed.
*/
void free_statistics_for_table(THD *thd, TABLE *table)
{
for (Field **field_ptr= table->field; *field_ptr; field_ptr++)
{
// Only delete the histograms that are exclusivly owned by this thread
if ((*field_ptr)->collected_stats &&
(*field_ptr)->collected_stats->histogram_ &&
(*field_ptr)->collected_stats->histogram_->get_owner() == thd)
{
delete (*field_ptr)->collected_stats->histogram_;
(*field_ptr)->collected_stats->histogram_= NULL;
}
}
}
/** /**
@brief @brief
...@@ -2921,7 +2949,7 @@ void Column_statistics_collected::finish(MEM_ROOT *mem_root, ha_rows rows, doubl ...@@ -2921,7 +2949,7 @@ void Column_statistics_collected::finish(MEM_ROOT *mem_root, ha_rows rows, doubl
if (hist_size != 0 && hist_type != INVALID_HISTOGRAM) if (hist_size != 0 && hist_type != INVALID_HISTOGRAM)
{ {
have_histogram= true; have_histogram= true;
histogram_= create_histogram(mem_root, hist_type); histogram_= create_histogram(mem_root, hist_type, current_thd);
histogram_->init_for_collection(mem_root, hist_type, hist_size); histogram_->init_for_collection(mem_root, hist_type, hist_size);
} }
......
...@@ -125,6 +125,7 @@ int read_statistics_for_tables(THD *thd, TABLE_LIST *tables); ...@@ -125,6 +125,7 @@ int read_statistics_for_tables(THD *thd, TABLE_LIST *tables);
int collect_statistics_for_table(THD *thd, TABLE *table); int collect_statistics_for_table(THD *thd, TABLE *table);
void delete_stat_values_for_table_share(TABLE_SHARE *table_share); void delete_stat_values_for_table_share(TABLE_SHARE *table_share);
int alloc_statistics_for_table(THD *thd, TABLE *table); int alloc_statistics_for_table(THD *thd, TABLE *table);
void free_statistics_for_table(THD *thd, TABLE *table);
int update_statistics_for_table(THD *thd, TABLE *table); 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_column(THD *thd, TABLE *tab, Field *col);
...@@ -176,6 +177,15 @@ class Histogram_base : public Sql_alloc ...@@ -176,6 +177,15 @@ class Histogram_base : public Sql_alloc
// Newer, JSON-based histograms may return 0. // Newer, JSON-based histograms may return 0.
virtual uint get_size()=0; virtual uint get_size()=0;
virtual ~Histogram_base()= default; virtual ~Histogram_base()= default;
Histogram_base() : owner(NULL) {}
THD *get_owner() { return owner; }
void set_owner(THD *thd) { owner=thd; }
private:
// Owner is a thread that *exclusively* owns this histogram (and so can
// delete it at any time)
THD *owner;
}; };
......
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