Commit 6859e80d authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-24351: S3, same-backend replication: Dropping a table on master...

..causes error on slave.
Cause: if the master doesn't have the frm file for the table,
DROP TABLE code will call ha_delete_table_force() to drop the table
in all available storage engines.
The issue was that this code path didn't check for
HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE flag for the storage engine,
and so did not add "... IF EXISTS" to the statement that's written
to the binary log.  This can cause error on the slave when it tries to
drop a table that's already gone.
parent 3ee24b23
...@@ -179,6 +179,26 @@ sync_slave_with_master; ...@@ -179,6 +179,26 @@ sync_slave_with_master;
--source include/show_binlog_events.inc --source include/show_binlog_events.inc
connection master; connection master;
--echo #
--echo # MDEV-24351: S3, same-backend replication: Dropping a table on master
--echo # causes error on slave
--echo #
show variables like 's3_replicate_alter_as_create_select';
connection slave;
create table t3 (a int, b int) engine=aria;
insert into t3 values (1,1),(2,2),(3,3);
alter table t3 engine=s3;
connection master;
let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
drop table t3;
--echo # Must show "DROP TABLE IF EXISTS t3", not just "DROP TABLE t3"
--source include/show_binlog_events.inc
sync_slave_with_master;
connection master;
--echo # --echo #
--echo # clean up --echo # clean up
--echo # --echo #
......
...@@ -272,6 +272,26 @@ slave-bin.000001 # Gtid # # GTID #-#-# ...@@ -272,6 +272,26 @@ slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1`,`t2` /* generated by server */ slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1`,`t2` /* generated by server */
connection master; connection master;
# #
# MDEV-24351: S3, same-backend replication: Dropping a table on master
# causes error on slave
#
show variables like 's3_replicate_alter_as_create_select';
Variable_name Value
s3_replicate_alter_as_create_select ON
connection slave;
create table t3 (a int, b int) engine=aria;
insert into t3 values (1,1),(2,2),(3,3);
alter table t3 engine=s3;
connection master;
drop table t3;
# Must show "DROP TABLE IF EXISTS t3", not just "DROP TABLE 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 `database`; DROP TABLE IF EXISTS `t3` /* generated by server */
connection slave;
connection master;
#
# clean up # clean up
# #
connection slave; connection slave;
......
...@@ -272,6 +272,26 @@ slave-bin.000001 # Gtid # # GTID #-#-# ...@@ -272,6 +272,26 @@ slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1`,`t2` /* generated by server */ slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1`,`t2` /* generated by server */
connection master; connection master;
# #
# MDEV-24351: S3, same-backend replication: Dropping a table on master
# causes error on slave
#
show variables like 's3_replicate_alter_as_create_select';
Variable_name Value
s3_replicate_alter_as_create_select ON
connection slave;
create table t3 (a int, b int) engine=aria;
insert into t3 values (1,1),(2,2),(3,3);
alter table t3 engine=s3;
connection master;
drop table t3;
# Must show "DROP TABLE IF EXISTS t3", not just "DROP TABLE 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 `database`; DROP TABLE IF EXISTS `t3` /* generated by server */
connection slave;
connection master;
#
# clean up # clean up
# #
connection slave; connection slave;
......
...@@ -5020,6 +5020,8 @@ static my_bool delete_table_force(THD *thd, plugin_ref plugin, void *arg) ...@@ -5020,6 +5020,8 @@ static my_bool delete_table_force(THD *thd, plugin_ref plugin, void *arg)
param->error= error; param->error= error;
if (error == 0) if (error == 0)
{ {
if (hton && hton->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE)
thd->replication_flags |= OPTION_IF_EXISTS;
param->error= 0; param->error= 0;
return TRUE; // Table was deleted return TRUE; // Table was deleted
} }
......
...@@ -2424,6 +2424,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2424,6 +2424,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
// note that for TABLE_TYPE_VIEW and TABLE_TYPE_UNKNOWN hton == NULL // note that for TABLE_TYPE_VIEW and TABLE_TYPE_UNKNOWN hton == NULL
} }
thd->replication_flags= 0;
was_view= table_type == TABLE_TYPE_VIEW; was_view= table_type == TABLE_TYPE_VIEW;
if ((table_type == TABLE_TYPE_UNKNOWN) || (was_view && !drop_view) || if ((table_type == TABLE_TYPE_UNKNOWN) || (was_view && !drop_view) ||
(table_type != TABLE_TYPE_SEQUENCE && drop_sequence)) (table_type != TABLE_TYPE_SEQUENCE && drop_sequence))
...@@ -2473,7 +2474,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2473,7 +2474,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
if (hton && hton->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE) if (hton && hton->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE)
log_if_exists= 1; log_if_exists= 1;
thd->replication_flags= 0;
bool enoent_warning= !dont_log_query && !(hton && hton->discover_table); bool enoent_warning= !dont_log_query && !(hton && hton->discover_table);
error= ha_delete_table(thd, hton, path, &db, &table_name, enoent_warning); error= ha_delete_table(thd, hton, path, &db, &table_name, enoent_warning);
...@@ -2489,9 +2489,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2489,9 +2489,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
goto err; goto err;
} }
} }
/* This may be set by the storage engine in handler::delete_table() */
if (thd->replication_flags & OPTION_IF_EXISTS)
log_if_exists= 1;
/* /*
Delete the .frm file if we managed to delete the table from the Delete the .frm file if we managed to delete the table from the
...@@ -2569,6 +2566,16 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -2569,6 +2566,16 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
error= ferror; error= ferror;
} }
/*
This may be set
- by the storage engine in handler::delete_table()
- when deleting a table without .frm file: delete_table_force() will
check if the storage engine that had the table had
HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE flag
*/
if (thd->replication_flags & OPTION_IF_EXISTS)
log_if_exists= 1;
if (likely(!error) || non_existing_table_error(error)) if (likely(!error) || non_existing_table_error(error))
{ {
if (Table_triggers_list::drop_all_triggers(thd, &db, &table_name, if (Table_triggers_list::drop_all_triggers(thd, &db, &table_name,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment