[Commits] c0fb7b4: MDEV-10555: Server crashes in mysql_admin_table upon killing ANALYZE

Oleksandr Byelkin sanja at mariadb.com
Mon Mar 13 16:31:12 EET 2017


revision-id: c0fb7b458bd6d555161994a5dd9f73495105cf66 (mariadb-10.2.4-46-gc0fb7b4)
parent(s): eded6243bc4796ab44e70403edd059d32225f589
committer: Oleksandr Byelkin
timestamp: 2017-03-13 15:31:12 +0100
message:

MDEV-10555: Server crashes in mysql_admin_table upon killing ANALYZE

Take into acount result of open table operation in mysql_admin_table.

---
 mysql-test/r/analyze_debug.result |  10 ++++
 mysql-test/t/analyze_debug.test   |  13 +++++
 sql/sql_admin.cc                  | 112 +++++++++++++++++++++++---------------
 3 files changed, 90 insertions(+), 45 deletions(-)

diff --git a/mysql-test/r/analyze_debug.result b/mysql-test/r/analyze_debug.result
new file mode 100644
index 0000000..2a11578
--- /dev/null
+++ b/mysql-test/r/analyze_debug.result
@@ -0,0 +1,10 @@
+SET @save_use_stat_tables= @@use_stat_tables;
+SET use_stat_tables= PREFERABLY;
+CREATE TABLE t1 (a int);
+insert into t1 values (1),(2),(3);
+SET STATEMENT debug_dbug="d,fail_2call_open_only_one_table" for
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	Operation failed
+drop table t1;
+SET use_stat_tables= @save_use_stat_tables;
diff --git a/mysql-test/t/analyze_debug.test b/mysql-test/t/analyze_debug.test
new file mode 100644
index 0000000..684011c
--- /dev/null
+++ b/mysql-test/t/analyze_debug.test
@@ -0,0 +1,13 @@
+
+--source include/have_debug.inc
+
+SET @save_use_stat_tables= @@use_stat_tables;
+SET use_stat_tables= PREFERABLY;
+CREATE TABLE t1 (a int);
+insert into t1 values (1),(2),(3);
+
+SET STATEMENT debug_dbug="d,fail_2call_open_only_one_table" for
+ANALYZE TABLE t1;
+
+drop table t1;
+SET use_stat_tables= @save_use_stat_tables;
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index bc5b9bd..95c2163 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -295,6 +295,10 @@ static inline bool table_not_corrupt_error(uint sql_errno)
           sql_errno == ER_WRONG_OBJECT);
 }
 
+#ifndef DBUG_OFF
+// It is counter for debugging fail on second call of open_only_one_table
+static int debug_fail_counter= 0;
+#endif
 
 static bool open_only_one_table(THD* thd, TABLE_LIST* table,
                                 bool repair_table_use_frm,
@@ -319,6 +323,16 @@ static bool open_only_one_table(THD* thd, TABLE_LIST* table,
   lex->query_tables_last= &table->next_global;
   lex->query_tables_own_last= 0;
 
+  DBUG_EXECUTE_IF("fail_2call_open_only_one_table", {
+                  if (debug_fail_counter)
+                  {
+                    open_error= TRUE;
+                    goto dbug_err;
+                  }
+                  else
+                    debug_fail_counter++;
+                  });
+
   /*
     CHECK TABLE command is allowed for views as well. Check on alter flags
     to differentiate from ALTER TABLE...CHECK PARTITION on which view is not
@@ -378,6 +392,9 @@ static bool open_only_one_table(THD* thd, TABLE_LIST* table,
     open_error= (thd->open_temporary_tables(table) ||
                  open_and_lock_tables(thd, table, TRUE, 0));
   }
+
+dbug_err:
+
   thd->prepare_derived_at_open= FALSE;
 
   /*
@@ -807,59 +824,64 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
                                       repair_table_use_frm, FALSE);
       thd->open_options&= ~extra_open_options;
 
-      TABLE *tab= table->table;
-      Field **field_ptr= tab->field;
-      if (!lex->column_list)
+      if (!open_error)
       {
-        bitmap_clear_all(tab->read_set);
-        for (uint fields= 0; *field_ptr; field_ptr++, fields++)
+        TABLE *tab= table->table;
+        Field **field_ptr= tab->field;
+        if (!lex->column_list)
         {
-          enum enum_field_types type= (*field_ptr)->type();
-          if (type < MYSQL_TYPE_MEDIUM_BLOB ||
-              type > MYSQL_TYPE_BLOB)
-            bitmap_set_bit(tab->read_set, fields);
-          else
-            push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
-                                ER_NO_EIS_FOR_FIELD,
-                                ER_THD(thd, ER_NO_EIS_FOR_FIELD),
-                                (*field_ptr)->field_name);
+          bitmap_clear_all(tab->read_set);
+          for (uint fields= 0; *field_ptr; field_ptr++, fields++)
+          {
+            enum enum_field_types type= (*field_ptr)->type();
+            if (type < MYSQL_TYPE_MEDIUM_BLOB ||
+                type > MYSQL_TYPE_BLOB)
+              bitmap_set_bit(tab->read_set, fields);
+            else
+              push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+                                  ER_NO_EIS_FOR_FIELD,
+                                  ER_THD(thd, ER_NO_EIS_FOR_FIELD),
+                                  (*field_ptr)->field_name);
+          }
         }
-      }
-      else
-      {
-        int pos;
-        LEX_STRING *column_name;
-        List_iterator_fast<LEX_STRING> it(*lex->column_list);
-
-        bitmap_clear_all(tab->read_set);
-        while ((column_name= it++))
+        else
         {
-          if (tab->s->fieldnames.type_names == 0 ||
-              (pos= find_type(&tab->s->fieldnames, column_name->str,
-                              column_name->length, 1)) <= 0)
+          int pos;
+          LEX_STRING *column_name;
+          List_iterator_fast<LEX_STRING> it(*lex->column_list);
+
+          bitmap_clear_all(tab->read_set);
+          while ((column_name= it++))
           {
-            compl_result_code= result_code= HA_ADMIN_INVALID;
-            break;
+            if (tab->s->fieldnames.type_names == 0 ||
+                (pos= find_type(&tab->s->fieldnames, column_name->str,
+                                column_name->length, 1)) <= 0)
+            {
+              compl_result_code= result_code= HA_ADMIN_INVALID;
+              break;
+            }
+            pos--;
+            enum enum_field_types type= tab->field[pos]->type();
+            if (type < MYSQL_TYPE_MEDIUM_BLOB ||
+                type > MYSQL_TYPE_BLOB)
+              bitmap_set_bit(tab->read_set, pos);
+            else
+              push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+                                  ER_NO_EIS_FOR_FIELD,
+                                  ER_THD(thd, ER_NO_EIS_FOR_FIELD),
+                                  column_name->str);
           }
-          pos--;
-          enum enum_field_types type= tab->field[pos]->type();
-          if (type < MYSQL_TYPE_MEDIUM_BLOB ||
-              type > MYSQL_TYPE_BLOB)
-            bitmap_set_bit(tab->read_set, pos);
-          else
-            push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
-                                ER_NO_EIS_FOR_FIELD,
-                                ER_THD(thd, ER_NO_EIS_FOR_FIELD),
-                                column_name->str);
+          tab->file->column_bitmaps_signal();
         }
-        tab->file->column_bitmaps_signal();
+        if (!(compl_result_code=
+              alloc_statistics_for_table(thd, table->table)) &&
+            !(compl_result_code=
+              collect_statistics_for_table(thd, table->table)))
+          compl_result_code= update_statistics_for_table(thd, table->table);
       }
-      if (!open_error &&
-          !(compl_result_code=
-            alloc_statistics_for_table(thd, table->table)) &&
-          !(compl_result_code=
-            collect_statistics_for_table(thd, table->table)))
-        compl_result_code= update_statistics_for_table(thd, table->table);
+      else
+        compl_result_code= HA_ADMIN_FAILED;
+
       if (compl_result_code)
         result_code= HA_ADMIN_FAILED;
       else


More information about the commits mailing list