1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

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.
This commit is contained in:
Sujatha
2019-08-14 22:53:16 +05:30
parent 2347ffd843
commit 29e560cdf3
3 changed files with 127 additions and 36 deletions

View File

@ -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));
}