Bug #11765416 (former 58381)
FAILED DROP DATABASE CAN BREAK STATEMENT BASED REPLICATION The first phase of DROP DATABASE is to delete the tables in the database. If deletion of one or more of the tables fail (e.g. due to a FOREIGN KEY constraint), DROP DATABASE will be aborted. However, some tables could still have been deleted. The problem was that nothing would be written to the binary log in this case, so any slaves would not delete these tables. Therefore the master and the slaves would get out of sync. This patch fixes the problem by making sure that DROP TABLE is written to the binary log for the tables that were in fact deleted by the failed DROP DATABASE statement. Test case added to binlog.binlog_database.test.
This commit is contained in:
parent
dd14e37661
commit
f94e7288e3
@ -30,3 +30,30 @@ drop table tt1, t1;
|
|||||||
source include/show_binlog_events.inc;
|
source include/show_binlog_events.inc;
|
||||||
|
|
||||||
FLUSH STATUS;
|
FLUSH STATUS;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
|
||||||
|
--echo # BASED REPLICATION
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP DATABASE IF EXISTS db1;
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE DATABASE db1;
|
||||||
|
CREATE TABLE db1.t1 (a INT);
|
||||||
|
CREATE TABLE db1.t2 (b INT, KEY(b)) engine=innodb;
|
||||||
|
CREATE TABLE t3 (a INT, KEY (a), FOREIGN KEY(a) REFERENCES db1.t2(b))
|
||||||
|
engine=innodb;
|
||||||
|
RESET MASTER;
|
||||||
|
|
||||||
|
--error ER_ROW_IS_REFERENCED
|
||||||
|
DROP DATABASE db1; # Fails because of the fk
|
||||||
|
SHOW TABLES FROM db1; # t1 was dropped, t2 remains
|
||||||
|
--source include/show_binlog_events.inc # Check that the binlog drops t1
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
DROP TABLE t3;
|
||||||
|
DROP DATABASE db1;
|
||||||
|
@ -39,6 +39,28 @@ master-bin.000001 # Query # # COMMIT
|
|||||||
master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE `tt1` /* generated by server */
|
master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE `tt1` /* generated by server */
|
||||||
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
||||||
FLUSH STATUS;
|
FLUSH STATUS;
|
||||||
|
#
|
||||||
|
# Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
|
||||||
|
# BASED REPLICATION
|
||||||
|
#
|
||||||
|
DROP DATABASE IF EXISTS db1;
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
|
CREATE DATABASE db1;
|
||||||
|
CREATE TABLE db1.t1 (a INT);
|
||||||
|
CREATE TABLE db1.t2 (b INT, KEY(b)) engine=innodb;
|
||||||
|
CREATE TABLE t3 (a INT, KEY (a), FOREIGN KEY(a) REFERENCES db1.t2(b))
|
||||||
|
engine=innodb;
|
||||||
|
RESET MASTER;
|
||||||
|
DROP DATABASE db1;
|
||||||
|
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
|
||||||
|
SHOW TABLES FROM db1;
|
||||||
|
Tables_in_db1
|
||||||
|
t2
|
||||||
|
show binlog events from <binlog_start>;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query # # use `db1`; drop table `t1`
|
||||||
|
DROP TABLE t3;
|
||||||
|
DROP DATABASE db1;
|
||||||
set binlog_format=mixed;
|
set binlog_format=mixed;
|
||||||
reset master;
|
reset master;
|
||||||
create database testing_1;
|
create database testing_1;
|
||||||
@ -80,6 +102,28 @@ master-bin.000001 # Query # # COMMIT
|
|||||||
master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE `tt1` /* generated by server */
|
master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE `tt1` /* generated by server */
|
||||||
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
||||||
FLUSH STATUS;
|
FLUSH STATUS;
|
||||||
|
#
|
||||||
|
# Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
|
||||||
|
# BASED REPLICATION
|
||||||
|
#
|
||||||
|
DROP DATABASE IF EXISTS db1;
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
|
CREATE DATABASE db1;
|
||||||
|
CREATE TABLE db1.t1 (a INT);
|
||||||
|
CREATE TABLE db1.t2 (b INT, KEY(b)) engine=innodb;
|
||||||
|
CREATE TABLE t3 (a INT, KEY (a), FOREIGN KEY(a) REFERENCES db1.t2(b))
|
||||||
|
engine=innodb;
|
||||||
|
RESET MASTER;
|
||||||
|
DROP DATABASE db1;
|
||||||
|
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
|
||||||
|
SHOW TABLES FROM db1;
|
||||||
|
Tables_in_db1
|
||||||
|
t2
|
||||||
|
show binlog events from <binlog_start>;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query # # use `db1`; drop table `t1`
|
||||||
|
DROP TABLE t3;
|
||||||
|
DROP DATABASE db1;
|
||||||
set binlog_format=row;
|
set binlog_format=row;
|
||||||
reset master;
|
reset master;
|
||||||
create database testing_1;
|
create database testing_1;
|
||||||
@ -122,6 +166,28 @@ master-bin.000001 # Query # # COMMIT
|
|||||||
master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE IF EXISTS `tt1` /* generated by server */
|
master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE IF EXISTS `tt1` /* generated by server */
|
||||||
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
|
||||||
FLUSH STATUS;
|
FLUSH STATUS;
|
||||||
|
#
|
||||||
|
# Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
|
||||||
|
# BASED REPLICATION
|
||||||
|
#
|
||||||
|
DROP DATABASE IF EXISTS db1;
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
|
CREATE DATABASE db1;
|
||||||
|
CREATE TABLE db1.t1 (a INT);
|
||||||
|
CREATE TABLE db1.t2 (b INT, KEY(b)) engine=innodb;
|
||||||
|
CREATE TABLE t3 (a INT, KEY (a), FOREIGN KEY(a) REFERENCES db1.t2(b))
|
||||||
|
engine=innodb;
|
||||||
|
RESET MASTER;
|
||||||
|
DROP DATABASE db1;
|
||||||
|
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
|
||||||
|
SHOW TABLES FROM db1;
|
||||||
|
Tables_in_db1
|
||||||
|
t2
|
||||||
|
show binlog events from <binlog_start>;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query # # use `db1`; drop table `t1`
|
||||||
|
DROP TABLE t3;
|
||||||
|
DROP DATABASE db1;
|
||||||
show databases;
|
show databases;
|
||||||
Database
|
Database
|
||||||
information_schema
|
information_schema
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc
|
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -833,12 +833,9 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
thd->push_internal_handler(&err_handler);
|
thd->push_internal_handler(&err_handler);
|
||||||
if (thd->killed ||
|
if (!thd->killed &&
|
||||||
(tables && mysql_rm_table_no_locks(thd, tables, true, false, true, true)))
|
!(tables &&
|
||||||
{
|
mysql_rm_table_no_locks(thd, tables, true, false, true, true)))
|
||||||
tables= NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We temporarily disable the binary log while dropping the objects
|
We temporarily disable the binary log while dropping the objects
|
||||||
@ -923,7 +920,7 @@ update_binlog:
|
|||||||
thd->server_status|= SERVER_STATUS_DB_DROPPED;
|
thd->server_status|= SERVER_STATUS_DB_DROPPED;
|
||||||
my_ok(thd, deleted_tables);
|
my_ok(thd, deleted_tables);
|
||||||
}
|
}
|
||||||
else if (mysql_bin_log.is_open())
|
else if (mysql_bin_log.is_open() && !silent)
|
||||||
{
|
{
|
||||||
char *query, *query_pos, *query_end, *query_data_start;
|
char *query, *query_pos, *query_end, *query_data_start;
|
||||||
TABLE_LIST *tbl;
|
TABLE_LIST *tbl;
|
||||||
@ -938,6 +935,16 @@ update_binlog:
|
|||||||
for (tbl= tables; tbl; tbl= tbl->next_local)
|
for (tbl= tables; tbl; tbl= tbl->next_local)
|
||||||
{
|
{
|
||||||
uint tbl_name_len;
|
uint tbl_name_len;
|
||||||
|
bool exists;
|
||||||
|
|
||||||
|
// Only write drop table to the binlog for tables that no longer exist.
|
||||||
|
if (check_if_table_exists(thd, tbl, &exists))
|
||||||
|
{
|
||||||
|
error= true;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (exists)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* 3 for the quotes and the comma*/
|
/* 3 for the quotes and the comma*/
|
||||||
tbl_name_len= strlen(tbl->table_name) + 3;
|
tbl_name_len= strlen(tbl->table_name) + 3;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user