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