diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-05-18 08:59:12 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-05-18 08:59:12 +0300 |
commit | 4240704abc2d51a2e46fb85049b601fce5d5b24c (patch) | |
tree | 7a5d40078f39746c649f27fa11ae75d44b509dec /sql/sql_admin.cc | |
parent | e861e057ad1b53e38887df66ac816626793c48cd (diff) | |
parent | ca3f497564f93d2d70d024d996bcd1136bddc5ab (diff) | |
download | mariadb-git-4240704abc2d51a2e46fb85049b601fce5d5b24c.tar.gz |
Merge 10.3 into 10.4
Diffstat (limited to 'sql/sql_admin.cc')
-rw-r--r-- | sql/sql_admin.cc | 77 |
1 files changed, 36 insertions, 41 deletions
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index a96eb58809b..273955b7541 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2010, 2015, Oracle and/or its affiliates. - Copyright (c) 2011, 2020, MariaDB + Copyright (c) 2011, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -497,7 +497,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, int (handler::*operator_func)(THD *, HA_CHECK_OPT *), int (view_operator_func)(THD *, TABLE_LIST*, - HA_CHECK_OPT *)) + HA_CHECK_OPT *), + bool is_cmd_replicated) { TABLE_LIST *table; List<Item> field_list; @@ -508,6 +509,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, int compl_result_code; bool need_repair_or_alter= 0; wait_for_commit* suspended_wfc; + bool is_table_modified= false; + DBUG_ENTER("mysql_admin_table"); DBUG_PRINT("enter", ("extra_open_options: %u", extra_open_options)); @@ -567,6 +570,10 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, bool open_for_modify= org_open_for_modify; DBUG_PRINT("admin", ("table: '%s'.'%s'", db, table->table_name.str)); + DEBUG_SYNC(thd, "admin_command_kill_before_modify"); + + if (thd->is_killed()) + break; strxmov(table_name, db, ".", table->table_name.str, NullS); thd->open_options|= extra_open_options; table->lock_type= lock_type; @@ -1219,6 +1226,13 @@ send_result_message: break; } } + /* + Admin commands acquire table locks and these locks are not detected by + parallel replication deadlock detection-and-handling mechanism. Hence + they must be marked as DDL so that they are not scheduled in parallel + with conflicting DMLs resulting in deadlock. + */ + thd->transaction.stmt.mark_executed_table_admin_cmd(); if (table->table && !table->view) { if (table->table->s->tmp_table) @@ -1254,10 +1268,9 @@ send_result_message: } else { - if (trans_commit_stmt(thd) || - (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END) && - trans_commit_implicit(thd))) + if (trans_commit_stmt(thd)) goto err; + is_table_modified= true; } close_thread_tables(thd); thd->release_transactional_locks(); @@ -1280,6 +1293,16 @@ send_result_message: if (protocol->write()) goto err; + DEBUG_SYNC(thd, "admin_command_kill_after_modify"); + } + if (is_table_modified && is_cmd_replicated && + (!opt_readonly || thd->slave_thread) && !thd->lex->no_write_to_binlog) + { + thd->get_stmt_da()->set_overwrite_status(true); + auto res= write_bin_log(thd, true, thd->query(), thd->query_length()); + thd->get_stmt_da()->set_overwrite_status(false); + if (res) + goto err; } my_eof(thd); @@ -1342,7 +1365,7 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, check_opt.key_cache= key_cache; DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, "assign_to_keycache", TL_READ_NO_INSERT, 0, 0, - 0, 0, &handler::assign_to_keycache, 0)); + 0, 0, &handler::assign_to_keycache, 0, false)); } @@ -1369,7 +1392,7 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables) */ DBUG_RETURN(mysql_admin_table(thd, tables, 0, "preload_keys", TL_READ_NO_INSERT, 0, 0, 0, 0, - &handler::preload_keys, 0)); + &handler::preload_keys, 0, false)); } @@ -1390,17 +1413,8 @@ bool Sql_cmd_analyze_table::execute(THD *thd) WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table); res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "analyze", lock_type, 1, 0, 0, 0, - &handler::ha_analyze, 0); - /* ! we write after unlocking the table */ - if (!res && !m_lex->no_write_to_binlog && (!opt_readonly || thd->slave_thread)) - { - /* - Presumably, ANALYZE and binlog writing doesn't require synchronization - */ - thd->get_stmt_da()->set_overwrite_status(true); - res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - thd->get_stmt_da()->set_overwrite_status(false); - } + &handler::ha_analyze, 0, true); + m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; @@ -1426,7 +1440,7 @@ bool Sql_cmd_check_table::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_check); + &handler::ha_check, &view_check, false); m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; @@ -1451,17 +1465,8 @@ bool Sql_cmd_optimize_table::execute(THD *thd) mysql_recreate_table(thd, first_table, true) : mysql_admin_table(thd, first_table, &m_lex->check_opt, "optimize", TL_WRITE, 1, 0, 0, 0, - &handler::ha_optimize, 0); - /* ! we write after unlocking the table */ - if (!res && !m_lex->no_write_to_binlog && (!opt_readonly || thd->slave_thread)) - { - /* - Presumably, OPTIMIZE and binlog writing doesn't require synchronization - */ - thd->get_stmt_da()->set_overwrite_status(true); - res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - thd->get_stmt_da()->set_overwrite_status(false); - } + &handler::ha_optimize, 0, true); + m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; @@ -1484,18 +1489,8 @@ bool Sql_cmd_repair_table::execute(THD *thd) TL_WRITE, 1, MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM), HA_OPEN_FOR_REPAIR, &prepare_for_repair, - &handler::ha_repair, &view_repair); + &handler::ha_repair, &view_repair, true); - /* ! we write after unlocking the table */ - if (!res && !m_lex->no_write_to_binlog && (!opt_readonly || thd->slave_thread)) - { - /* - Presumably, REPAIR and binlog writing doesn't require synchronization - */ - thd->get_stmt_da()->set_overwrite_status(true); - res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - thd->get_stmt_da()->set_overwrite_status(false); - } m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; |