Skip to content

Commit ccc3a46

Browse files
authored andcommitted
Bug #49137 Replication failure on SBR/MBR + multi-table DROP TEMPORARY TABLE
In statement-based or mixed-mode replication, use DROP TEMPORARY TABLE to drop multiple tables causes different errors on master and slave, when one or more of these tables do not exist. Because when executed on slave, it would automatically add IF EXISTS to the query to ignore all ER_BAD_TABLE_ERROR errors. To fix the problem, do not add IF EXISTS when executing DROP TEMPORARY TABLE on the slave, and clear the ER_BAD_TABLE_ERROR error after execution if the query does not expect any errors.
1 parent 6c16fb6 commit ccc3a46

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

mysql-test/r/rpl_drop_temp.result

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,17 @@ show status like 'Slave_open_temp_tables';
1818
Variable_name Value
1919
Slave_open_temp_tables 0
2020
drop database mysqltest;
21+
DROP TEMPORARY TABLE IF EXISTS tmp1;
22+
Warnings:
23+
Note 1051 Unknown table 'tmp1'
24+
CREATE TEMPORARY TABLE t1 ( a int );
25+
DROP TEMPORARY TABLE t1, t2;
26+
ERROR 42S02: Unknown table 't2'
27+
DROP TEMPORARY TABLE tmp2;
28+
ERROR 42S02: Unknown table 'tmp2'
29+
stop slave;
30+
**** On Master ****
31+
CREATE TEMPORARY TABLE tmp3 (a int);
32+
DROP TEMPORARY TABLE tmp3;
33+
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
34+
START SLAVE;

mysql-test/t/rpl_drop_temp.test

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,38 @@ connection slave;
2020
show status like 'Slave_open_temp_tables';
2121
connection master;
2222
drop database mysqltest;
23+
sync_slave_with_master;
24+
25+
#
26+
# Bug#49137
27+
# This test verifies if DROP MULTI TEMPORARY TABLE
28+
# will cause different errors on master and slave,
29+
# when one or more of these tables do not exist.
30+
#
31+
32+
connection master;
33+
DROP TEMPORARY TABLE IF EXISTS tmp1;
34+
CREATE TEMPORARY TABLE t1 ( a int );
35+
--error 1051
36+
DROP TEMPORARY TABLE t1, t2;
37+
--error 1051
38+
DROP TEMPORARY TABLE tmp2;
39+
sync_slave_with_master;
40+
41+
connection slave;
42+
stop slave;
43+
wait_for_slave_to_stop;
44+
45+
--echo **** On Master ****
46+
connection master;
47+
CREATE TEMPORARY TABLE tmp3 (a int);
48+
DROP TEMPORARY TABLE tmp3;
49+
50+
connection slave;
51+
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
52+
START SLAVE;
53+
54+
connection master;
55+
sync_slave_with_master;
2356

2457
# End of 4.1 tests

sql/log_event.cc

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2103,7 +2103,17 @@ START SLAVE; . Query: '%s'", expected_error, thd->query);
21032103

21042104
compare_errors:
21052105

2106-
/*
2106+
/*
2107+
In the slave thread, we may sometimes execute some DROP / * 40005
2108+
TEMPORARY * / TABLE that come from parts of binlogs (likely if we
2109+
use RESET SLAVE or CHANGE MASTER TO), while the temporary table
2110+
has already been dropped. To ignore such irrelevant "table does
2111+
not exist errors", we silently clear the error if TEMPORARY was used.
2112+
*/
2113+
if (thd->lex->drop_temporary &&
2114+
thd->net.last_errno == ER_BAD_TABLE_ERROR && !expected_error)
2115+
thd->clear_error();
2116+
/*
21072117
If we expected a non-zero error code, and we don't get the same error
21082118
code, and none of them should be ignored.
21092119
*/

sql/sql_parse.cc

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4038,17 +4038,6 @@ mysql_execute_command(THD *thd)
40384038
}
40394039
else
40404040
{
4041-
/*
4042-
If this is a slave thread, we may sometimes execute some
4043-
DROP / * 40005 TEMPORARY * / TABLE
4044-
that come from parts of binlogs (likely if we use RESET SLAVE or CHANGE
4045-
MASTER TO), while the temporary table has already been dropped.
4046-
To not generate such irrelevant "table does not exist errors",
4047-
we silently add IF EXISTS if TEMPORARY was used.
4048-
*/
4049-
if (thd->slave_thread)
4050-
lex->drop_if_exists= 1;
4051-
40524041
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
40534042
thd->transaction.all.modified_non_trans_table= TRUE;
40544043
}

0 commit comments

Comments
 (0)