From 29e560cdf32a2c6aa10298c2404bbeb54e628d6e Mon Sep 17 00:00:00 2001 From: Sujatha Date: Wed, 14 Aug 2019 22:53:16 +0530 Subject: MDEV-20348: DROP TABLE IF EXISTS killed on master but was replicated Problem: ======= DROP TABLE IF EXISTS was killed. The table still exists on the master but the DDL was still logged. Analysis: ========= During the execution of DROP TABLE command "ha_delete_table" call is invoked to delete the table. If the query is killed at this point, the kill command is not handled within the code. This results in two issues. 1) The table which is not dropped also gets written into the binary log. 2) The code continues further upon receiving 'KILL QUERY'. Fix: === Upon receiving the KILL command the query should stop its current execution. Tables which were successfully dropped prior to KILL command should be included in the binary log. --- sql/sql_table.cc | 67 ++++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 36 deletions(-) (limited to 'sql/sql_table.cc') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9d7e03727d3..cc58dc4a7e8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2362,35 +2362,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, path_length= build_table_filename(path, sizeof(path) - 1, db, alias, reg_ext, 0); - /* - This handles the case where a "DROP" was executed and a regular - table "may be" dropped as drop_temporary is FALSE and error is - TRUE. If the error was FALSE a temporary table was dropped and - regardless of the status of drop_temporary a "DROP TEMPORARY" - must be used. - */ - if (!dont_log_query) - { - /* - Note that unless if_exists is TRUE or a temporary table was deleted, - there is no means to know if the statement should be written to the - binary log. See further information on this variable in what follows. - */ - non_tmp_table_deleted= (if_exists ? TRUE : non_tmp_table_deleted); - /* - Don't write the database name if it is the current one (or if - thd->db is NULL). - */ - if (thd->db == NULL || strcmp(db,thd->db) != 0) - { - append_identifier(thd, &built_query, db, db_length); - built_query.append("."); - } - - append_identifier(thd, &built_query, table->table_name, - table->table_name_length); - built_query.append(","); - } } DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table"); error= 0; @@ -2464,14 +2435,20 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, // Remove extension for delete *(end= path + path_length - reg_ext_length)= '\0'; - error= ha_delete_table(thd, table_type, path, db, table->table_name, - !dont_log_query); - - if (!error) + if ((error= ha_delete_table(thd, table_type, path, db, table->table_name, + !dont_log_query))) + { + if (thd->is_killed()) + { + error= -1; + goto err; + } + } + else { int frm_delete_error, trigger_drop_error= 0; - /* Delete the table definition file */ - strmov(end,reg_ext); + /* Delete the table definition file */ + strmov(end,reg_ext); if (table_type && table_type != view_pseudo_hton && table_type->discover_table) { @@ -2505,7 +2482,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, if (error) { if (wrong_tables.length()) - wrong_tables.append(','); + wrong_tables.append(','); wrong_tables.append(db); wrong_tables.append('.'); wrong_tables.append(table->table_name); @@ -2518,6 +2495,24 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, mysql_audit_drop_table(thd, table); } + if (!dont_log_query && !drop_temporary) + { + non_tmp_table_deleted= (if_exists ? TRUE : non_tmp_table_deleted); + /* + Don't write the database name if it is the current one (or if + thd->db is NULL). + */ + if (thd->db == NULL || strcmp(db,thd->db) != 0) + { + append_identifier(thd, &built_query, db, db_length); + built_query.append("."); + } + + append_identifier(thd, &built_query, table->table_name, + table->table_name_length); + built_query.append(","); + } + DBUG_PRINT("table", ("table: %p s: %p", table->table, table->table ? table->table->s : NULL)); } -- cgit v1.2.1