From 321f589c81105ef9fc23689b7ec8eec3ff98ed39 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 4 Aug 2014 21:36:02 +0200 Subject: [PATCH] MDEV-6181 EITS could eat all tmpdir space and hang Don't ignore errors from Count_distinct_field::add(), pass them to the caller, so that it could abort the data collection loop. --- mysql-test/r/stat_tables-enospc.result | 10 ++++++++++ mysql-test/t/stat_tables-enospc.test | 23 +++++++++++++++++++++++ sql/sql_statistics.cc | 15 ++++++++++----- 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 mysql-test/r/stat_tables-enospc.result create mode 100644 mysql-test/t/stat_tables-enospc.test diff --git a/mysql-test/r/stat_tables-enospc.result b/mysql-test/r/stat_tables-enospc.result new file mode 100644 index 00000000000..f0d76f04eee --- /dev/null +++ b/mysql-test/r/stat_tables-enospc.result @@ -0,0 +1,10 @@ +call mtr.add_suppression("No space left on device"); +create table t1 (a varchar(255), b varchar(255), c varchar(255)); +set use_stat_tables=PREFERABLY, optimizer_use_condition_selectivity=3; +set debug_dbug='+d,simulate_file_write_error'; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze Error Error writing file 'tmp-file' (Errcode: 28 "No space left on device") +test.t1 analyze status Operation failed +set debug_dbug=''; +drop table t1; diff --git a/mysql-test/t/stat_tables-enospc.test b/mysql-test/t/stat_tables-enospc.test new file mode 100644 index 00000000000..12e42f6adc0 --- /dev/null +++ b/mysql-test/t/stat_tables-enospc.test @@ -0,0 +1,23 @@ +# +# MDEV-6181 EITS could eat all tmpdir space and hang +# +# test that ANALYZE TABLE is immediately aborted when going out of disk space +--source include/have_debug.inc +call mtr.add_suppression("No space left on device"); +create table t1 (a varchar(255), b varchar(255), c varchar(255)); +--disable_query_log +let $i=10000; +while ($i) { + insert t1 values (repeat(format(rand(),10), 20), + repeat(format(rand(),10), 20), + repeat(format(rand(),10), 20)); + dec $i; +} +--enable_query_log +set use_stat_tables=PREFERABLY, optimizer_use_condition_selectivity=3; +set debug_dbug='+d,simulate_file_write_error'; +--replace_regex /'.*'/'tmp-file'/ +analyze table t1; +set debug_dbug=''; +drop table t1; + diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 7773b648748..9acd3d98322 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -184,7 +184,7 @@ private: public: inline void init(THD *thd, Field * table_field); - inline void add(ha_rows rowno); + inline bool add(ha_rows rowno); inline void finish(ha_rows rows); inline void cleanup(); }; @@ -2219,9 +2219,10 @@ void Column_statistics_collected::init(THD *thd, Field *table_field) */ inline -void Column_statistics_collected::add(ha_rows rowno) +bool Column_statistics_collected::add(ha_rows rowno) { + bool err= 0; if (column->is_null()) nulls++; else @@ -2232,8 +2233,9 @@ void Column_statistics_collected::add(ha_rows rowno) if (max_value && column->update_max(max_value, rowno == nulls)) set_not_null(COLUMN_STAT_MAX_VALUE); if (count_distinct) - count_distinct->add(); + err= count_distinct->add(); } + return err; } @@ -2487,8 +2489,11 @@ int collect_statistics_for_table(THD *thd, TABLE *table) table_field= *field_ptr; if (!bitmap_is_set(table->read_set, table_field->field_index)) continue; - table_field->collected_stats->add(rows); + if ((rc= table_field->collected_stats->add(rows))) + break; } + if (rc) + break; rows++; } file->ha_rnd_end(); @@ -2518,7 +2523,7 @@ int collect_statistics_for_table(THD *thd, TABLE *table) else table_field->collected_stats->cleanup(); } -bitmap_clear_all(table->write_set); + bitmap_clear_all(table->write_set); if (!rc) {