Skip to content

Commit 6859e80

Browse files
committed
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.
1 parent 3ee24b2 commit 6859e80

File tree

5 files changed

+73
-4
lines changed

5 files changed

+73
-4
lines changed

mysql-test/suite/s3/replication.inc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,26 @@ sync_slave_with_master;
179179
--source include/show_binlog_events.inc
180180
connection master;
181181

182+
--echo #
183+
--echo # MDEV-24351: S3, same-backend replication: Dropping a table on master
184+
--echo # causes error on slave
185+
--echo #
186+
show variables like 's3_replicate_alter_as_create_select';
187+
188+
connection slave;
189+
create table t3 (a int, b int) engine=aria;
190+
insert into t3 values (1,1),(2,2),(3,3);
191+
alter table t3 engine=s3;
192+
193+
connection master;
194+
let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
195+
drop table t3;
196+
--echo # Must show "DROP TABLE IF EXISTS t3", not just "DROP TABLE t3"
197+
--source include/show_binlog_events.inc
198+
199+
sync_slave_with_master;
200+
connection master;
201+
182202
--echo #
183203
--echo # clean up
184204
--echo #

mysql-test/suite/s3/replication_mixed.result

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,26 @@ slave-bin.000001 # Gtid # # GTID #-#-#
272272
slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1`,`t2` /* generated by server */
273273
connection master;
274274
#
275+
# MDEV-24351: S3, same-backend replication: Dropping a table on master
276+
# causes error on slave
277+
#
278+
show variables like 's3_replicate_alter_as_create_select';
279+
Variable_name Value
280+
s3_replicate_alter_as_create_select ON
281+
connection slave;
282+
create table t3 (a int, b int) engine=aria;
283+
insert into t3 values (1,1),(2,2),(3,3);
284+
alter table t3 engine=s3;
285+
connection master;
286+
drop table t3;
287+
# Must show "DROP TABLE IF EXISTS t3", not just "DROP TABLE t3"
288+
include/show_binlog_events.inc
289+
Log_name Pos Event_type Server_id End_log_pos Info
290+
master-bin.000001 # Gtid # # GTID #-#-#
291+
master-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t3` /* generated by server */
292+
connection slave;
293+
connection master;
294+
#
275295
# clean up
276296
#
277297
connection slave;

mysql-test/suite/s3/replication_stmt.result

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,26 @@ slave-bin.000001 # Gtid # # GTID #-#-#
272272
slave-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t1`,`t2` /* generated by server */
273273
connection master;
274274
#
275+
# MDEV-24351: S3, same-backend replication: Dropping a table on master
276+
# causes error on slave
277+
#
278+
show variables like 's3_replicate_alter_as_create_select';
279+
Variable_name Value
280+
s3_replicate_alter_as_create_select ON
281+
connection slave;
282+
create table t3 (a int, b int) engine=aria;
283+
insert into t3 values (1,1),(2,2),(3,3);
284+
alter table t3 engine=s3;
285+
connection master;
286+
drop table t3;
287+
# Must show "DROP TABLE IF EXISTS t3", not just "DROP TABLE t3"
288+
include/show_binlog_events.inc
289+
Log_name Pos Event_type Server_id End_log_pos Info
290+
master-bin.000001 # Gtid # # GTID #-#-#
291+
master-bin.000001 # Query # # use `database`; DROP TABLE IF EXISTS `t3` /* generated by server */
292+
connection slave;
293+
connection master;
294+
#
275295
# clean up
276296
#
277297
connection slave;

sql/handler.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5020,6 +5020,8 @@ static my_bool delete_table_force(THD *thd, plugin_ref plugin, void *arg)
50205020
param->error= error;
50215021
if (error == 0)
50225022
{
5023+
if (hton && hton->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE)
5024+
thd->replication_flags |= OPTION_IF_EXISTS;
50235025
param->error= 0;
50245026
return TRUE; // Table was deleted
50255027
}

sql/sql_table.cc

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,6 +2424,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
24242424
// note that for TABLE_TYPE_VIEW and TABLE_TYPE_UNKNOWN hton == NULL
24252425
}
24262426

2427+
thd->replication_flags= 0;
24272428
was_view= table_type == TABLE_TYPE_VIEW;
24282429
if ((table_type == TABLE_TYPE_UNKNOWN) || (was_view && !drop_view) ||
24292430
(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,
24732474
if (hton && hton->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE)
24742475
log_if_exists= 1;
24752476

2476-
thd->replication_flags= 0;
24772477
bool enoent_warning= !dont_log_query && !(hton && hton->discover_table);
24782478
error= ha_delete_table(thd, hton, path, &db, &table_name, enoent_warning);
24792479

@@ -2489,9 +2489,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
24892489
goto err;
24902490
}
24912491
}
2492-
/* This may be set by the storage engine in handler::delete_table() */
2493-
if (thd->replication_flags & OPTION_IF_EXISTS)
2494-
log_if_exists= 1;
24952492

24962493
/*
24972494
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,
25692566
error= ferror;
25702567
}
25712568

2569+
/*
2570+
This may be set
2571+
- by the storage engine in handler::delete_table()
2572+
- when deleting a table without .frm file: delete_table_force() will
2573+
check if the storage engine that had the table had
2574+
HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE flag
2575+
*/
2576+
if (thd->replication_flags & OPTION_IF_EXISTS)
2577+
log_if_exists= 1;
2578+
25722579
if (likely(!error) || non_existing_table_error(error))
25732580
{
25742581
if (Table_triggers_list::drop_all_triggers(thd, &db, &table_name,

0 commit comments

Comments
 (0)