Skip to content
Permalink
Browse files

MDEV-20348: DROP TABLE IF EXISTS killed on master but was replicated

Merge branch '10.2' into 10.3
  • Loading branch information...
sujatha-s committed Aug 15, 2019
2 parents ae34d85 + 29e560c commit 828191b6a0d2ea262783c7d0c217001c57fa1024
@@ -0,0 +1,32 @@
include/master-slave.inc
[connection master]
create table t1 (a int) engine=innodb;
create table t2 (b longblob) engine=innodb;
create table t3 (c int) engine=innodb;
insert into t2 values (repeat('b',1024*1024));
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
set debug_sync='rm_table_no_locks_before_delete_table SIGNAL nogo WAIT_FOR go EXECUTE 2';
drop table t1, t2, t3;
connect foo,localhost,root;
set debug_sync='now SIGNAL go';
kill query CONNECTION_ID;
connection master;
ERROR 70100: Query execution was interrupted
"Tables t2 and t3 should be listed"
SHOW TABLES;
Tables_in_test
t2
t3
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
connection slave;
drop table t2, t3;
connection master;
set debug_sync='RESET';
drop table t2, t3;
include/rpl_end.inc
@@ -0,0 +1,64 @@
# ==== Purpose ====
#
# Check that when the execution of a DROP TABLE command with single table
# fails it should not be written to the binary log. Also test that when the
# execution of DROP TABLE command with multiple tables fails the command
# should be written into the binary log.
#
# ==== Implementation ====
#
# Steps:
# 0 - Create tables named t1, t2, t3
# 1 - Execute DROP TABLE t1,t2,t3 command.
# 2 - Kill the DROP TABLE command while it is trying to drop table 't2'.
# 3 - Verify that tables t2,t3 are present after the DROP command execution
# was interrupted.
# 4 - Check that table 't1' is present in binary log as part of DROP
# command.
#
# ==== References ====
#
# MDEV-20348: DROP TABLE IF EXISTS killed on master but was replicated.
#

--source include/have_innodb.inc
--source include/have_debug_sync.inc
--source include/have_binlog_format_statement.inc
--source include/master-slave.inc

create table t1 (a int) engine=innodb;
create table t2 (b longblob) engine=innodb;
create table t3 (c int) engine=innodb;
insert into t2 values (repeat('b',1024*1024));
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);

let $id=`select connection_id()`;
set debug_sync='rm_table_no_locks_before_delete_table SIGNAL nogo WAIT_FOR go EXECUTE 2';
send drop table t1, t2, t3;

connect foo,localhost,root;
set debug_sync='now SIGNAL go';
let $wait_condition=select 1 from information_schema.processlist where state like 'debug sync point:%';
source include/wait_condition.inc;
--replace_result $id CONNECTION_ID
eval kill query $id;

connection master;
error ER_QUERY_INTERRUPTED;
reap;

--echo "Tables t2 and t3 should be listed"
SHOW TABLES;
--source include/show_binlog_events.inc
--sync_slave_with_master
drop table t2, t3;

connection master;
set debug_sync='RESET';
drop table t2, t3;

source include/rpl_end.inc;
@@ -2403,35 +2403,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
/* remove .frm file and engine files */
path_length= build_table_filename(path, sizeof(path) - 1, db.str, alias.str,
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.str == NULL || cmp(&db, &thd->db) != 0)
{
append_identifier(thd, &built_query, &db);
built_query.append(".");
}

append_identifier(thd, &built_query, &table->table_name);
built_query.append(",");
}
}
DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table");
error= 0;
@@ -2511,9 +2482,16 @@ 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
{
/* Delete the table definition file */
strmov(end,reg_ext);
@@ -2557,7 +2535,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);
@@ -2570,6 +2548,22 @@ 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.str == NULL || cmp(&db, &thd->db) != 0)
{
append_identifier(thd, &built_query, &db);
built_query.append(".");
}

append_identifier(thd, &built_query, &table->table_name);
built_query.append(",");
}
DBUG_PRINT("table", ("table: %p s: %p", table->table,
table->table ? table->table->s : NULL));
}

0 comments on commit 828191b

Please sign in to comment.
You can’t perform that action at this time.