From 3b961347db2b2ad1d31cf64829a6d0e31795e158 Mon Sep 17 00:00:00 2001
From: Kristian Nielsen <knielsen@knielsen-hq.org>
Date: Wed, 8 Apr 2015 11:01:18 +0200
Subject: MDEV-7888, MDEV-7929: Parallel replication hangs sometimes on ANALYZE
 TABLE or DDL

The hangs occur when the group_commit_orderer object is freed before the last
mark_start_commit() call on it - this loses the wakeup to other waiting worker
threads, causing them to hang until killed manually.

The object was freed because wakeup_subsequent_commits() was called two early
in two places. For MDEV-7888, during ANALYZE TABLE, and for MDEV-7929 during
record_gtid() after processing a DDL event. The group_commit_orderer object
can be freed when its last transaction has called wait_for_prior_commit().

Fix by implementing a suspend/resume mechanism for wakeup_subsequent_commits()
that can be used in places where a transaction is committed without this being
the commit of the actual replication event group.

Also add a protection mechanism (that asserts in debug builds) which can
prevent the too-early free and hang if other similar bugs should remain in
other parts of the code.
---
 sql/sql_admin.cc | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

(limited to 'sql/sql_admin.cc')

diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 1d917de0c1a..ce8302af0b3 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -320,6 +320,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
   int result_code;
   int compl_result_code;
   bool need_repair_or_alter= 0;
+  wait_for_commit* suspended_wfc;
 
   DBUG_ENTER("mysql_admin_table");
   DBUG_PRINT("enter", ("extra_open_options: %u", extra_open_options));
@@ -337,6 +338,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
     DBUG_RETURN(TRUE);
 
+  /*
+    This function calls trans_commit() during its operation, but that does not
+    imply that the operation is complete or binlogged. So we have to suspend
+    temporarily the wakeup_subsequent_commits() calls (if used).
+  */
+  suspended_wfc= thd->suspend_subsequent_commits();
+
   mysql_ha_rm_tables(thd, tables);
 
   /*
@@ -464,7 +472,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
           if (!table->table->part_info)
           {
             my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
-            DBUG_RETURN(TRUE);
+            goto err2;
           }
           if (set_part_state(alter_info, table->table->part_info, PART_ADMIN))
           {
@@ -1045,6 +1053,8 @@ send_result_message:
   }
 
   my_eof(thd);
+  thd->resume_subsequent_commits(suspended_wfc);
+  DBUG_EXECUTE_IF("inject_analyze_table_sleep", my_sleep(500000););
   DBUG_RETURN(FALSE);
 
 err:
@@ -1058,6 +1068,8 @@ err:
   }
   close_thread_tables(thd);			// Shouldn't be needed
   thd->mdl_context.release_transactional_locks();
+err2:
+  thd->resume_subsequent_commits(suspended_wfc);
   DBUG_RETURN(TRUE);
 }
 
-- 
cgit v1.2.1


From c8dbef22add27eb6cc737b12eb80b968663d34bb Mon Sep 17 00:00:00 2001
From: Oleksandr Byelkin <sanja@askmonty.org>
Date: Sun, 12 Apr 2015 20:41:28 +1000
Subject: MDEV-6916 REPAIR VIEW / mysql migration

from: r4407
---
 sql/sql_admin.cc | 44 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 36 insertions(+), 8 deletions(-)

(limited to 'sql/sql_admin.cc')

diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 92aa414b569..20c23afe228 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -314,7 +314,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
                                                   HA_CHECK_OPT *),
                               int (handler::*operator_func)(THD *,
                                                             HA_CHECK_OPT *),
-                              int (view_operator_func)(THD *, TABLE_LIST*))
+                              int (view_operator_func)(THD *, TABLE_LIST*,
+                                                       HA_CHECK_OPT *))
 {
   TABLE_LIST *table;
   SELECT_LEX *select= &thd->lex->select_lex;
@@ -380,7 +381,18 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
       lex->query_tables_own_last= 0;
 
       if (view_operator_func == NULL)
+      {
         table->required_type=FRMTYPE_TABLE;
+        DBUG_ASSERT(!lex->only_view);
+      }
+      else if (lex->only_view)
+      {
+        table->required_type= FRMTYPE_VIEW;
+      }
+      else if (!lex->only_view && lex->sql_command == SQLCOM_REPAIR)
+      {
+        table->required_type= FRMTYPE_TABLE;
+      }
 
       if (lex->sql_command == SQLCOM_CHECK ||
           lex->sql_command == SQLCOM_REPAIR ||
@@ -506,9 +518,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
     }
 
     /*
-      CHECK TABLE command is only command where VIEW allowed here and this
-      command use only temporary teble method for VIEWs resolving => there
-      can't be VIEW tree substitition of join view => if opening table
+      CHECK/REPAIR TABLE command is only command where VIEW allowed here and
+      this command use only temporary table method for VIEWs resolving =>
+      there can't be VIEW tree substitition of join view => if opening table
       succeed then table->table will have real TABLE pointer as value (in
       case of join view substitution table->table can be 0, but here it is
       impossible)
@@ -521,7 +533,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
                      ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
       /* if it was a view will check md5 sum */
       if (table->view &&
-          view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
+          view_check(thd, table, check_opt) == HA_ADMIN_WRONG_CHECKSUM)
         push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                      ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
       if (thd->stmt_da->is_error() &&
@@ -536,7 +548,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
     if (table->view)
     {
       DBUG_PRINT("admin", ("calling view_operator_func"));
-      result_code= (*view_operator_func)(thd, table);
+      result_code= (*view_operator_func)(thd, table, check_opt);
       goto send_result;
     }
 
@@ -867,6 +879,22 @@ send_result_message:
       fatal_error=1;
       break;
     }
+    case HA_ADMIN_VIEW_REPAIR_IS_DONE:
+    {
+      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+      protocol->store(ER(ER_VIEW_REPAIR_IS_DONE),
+                      strlen(ER(ER_VIEW_REPAIR_IS_DONE)),
+                      system_charset_info);
+      break;
+    }
+    case HA_ADMIN_NEEDS_REPAIR:
+    {
+      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+      protocol->store(ER(ER_NEEDS_REPAIR),
+                      strlen(ER(ER_NEEDS_REPAIR)),
+                      system_charset_info);
+      break;
+    }
 
     default:				// Probably HA_ADMIN_INTERNAL_ERROR
       {
@@ -1071,7 +1099,7 @@ bool Check_table_statement::execute(THD *thd)
 
   res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "check",
                          lock_type, 0, 0, HA_OPEN_FOR_REPAIR, 0,
-                         &handler::ha_check, &view_checksum);
+                         &handler::ha_check, &view_check);
 
   m_lex->select_lex.table_list.first= first_table;
   m_lex->query_tables= first_table;
@@ -1126,7 +1154,7 @@ bool Repair_table_statement::execute(THD *thd)
                          TL_WRITE, 1,
                          test(m_lex->check_opt.sql_flags & TT_USEFRM),
                          HA_OPEN_FOR_REPAIR, &prepare_for_repair,
-                         &handler::ha_repair, 0);
+                         &handler::ha_repair, &view_repair);
 
   /* ! we write after unlocking the table */
   if (!res && !m_lex->no_write_to_binlog)
-- 
cgit v1.2.1


From 4409e04d891fba62a3f4ed291c96ee34d645dbec Mon Sep 17 00:00:00 2001
From: Daniel Black <grooverdan@users.sourceforge.net>
Date: Sun, 12 Apr 2015 21:40:07 +1000
Subject: correct server side error messages

---
 sql/sql_admin.cc | 16 ----------------
 1 file changed, 16 deletions(-)

(limited to 'sql/sql_admin.cc')

diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 20c23afe228..65292a526fa 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -879,22 +879,6 @@ send_result_message:
       fatal_error=1;
       break;
     }
-    case HA_ADMIN_VIEW_REPAIR_IS_DONE:
-    {
-      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
-      protocol->store(ER(ER_VIEW_REPAIR_IS_DONE),
-                      strlen(ER(ER_VIEW_REPAIR_IS_DONE)),
-                      system_charset_info);
-      break;
-    }
-    case HA_ADMIN_NEEDS_REPAIR:
-    {
-      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
-      protocol->store(ER(ER_NEEDS_REPAIR),
-                      strlen(ER(ER_NEEDS_REPAIR)),
-                      system_charset_info);
-      break;
-    }
 
     default:				// Probably HA_ADMIN_INTERNAL_ERROR
       {
-- 
cgit v1.2.1


From 6f17e233bf7f4de20dda8fb31f63aa52452c4e0a Mon Sep 17 00:00:00 2001
From: Sergei Golubchik <serg@mariadb.org>
Date: Tue, 28 Apr 2015 21:24:32 +0200
Subject: post-merge fixes

---
 sql/sql_admin.cc | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

(limited to 'sql/sql_admin.cc')

diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 65292a526fa..44057b6220e 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -869,7 +869,16 @@ send_result_message:
       size_t length;
 
       protocol->store(STRING_WITH_LEN("error"), system_charset_info);
-      if (table->table->file->ha_table_flags() & HA_CAN_REPAIR)
+#if MYSQL_VERSION_ID > 100104
+#error fix the error message to take TABLE or VIEW as an argument
+#else
+      if (table->view)
+        length= my_snprintf(buf, sizeof(buf),
+                            "Upgrade required. Please do \"REPAIR VIEW %`s\" or dump/reload to fix it!",
+                            table->table_name);
+      else
+#endif
+      if (table->table->file->ha_table_flags() & HA_CAN_REPAIR || table->view)
         length= my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE),
                             table->table_name);
       else
-- 
cgit v1.2.1


From 0014bdc7eef141dcd66930e853242b3be4960831 Mon Sep 17 00:00:00 2001
From: Sergei Golubchik <serg@mariadb.org>
Date: Thu, 7 May 2015 22:18:34 +0200
Subject: MDEV-8115 mysql_upgrade crashes the server with REPAIR VIEW

on REPAIR don't do table-specific stuff for views
(because even if the view has a temp table opened for it,
it's not opened all the way down the engine. In particular,
Aria crashes in maria_status() because MARIA_HA* info - that is
table->table->file->file - is NULL)
---
 sql/sql_admin.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sql/sql_admin.cc')

diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 44057b6220e..9827c67065c 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -901,7 +901,7 @@ send_result_message:
         break;
       }
     }
-    if (table->table)
+    if (table->table && !table->view)
     {
       if (table->table->s->tmp_table)
       {
-- 
cgit v1.2.1