Commit 5da083ef authored by s.sujatha's avatar s.sujatha

Bug#20041860: SLAVE ERROR WHEN DROP DATABASE

Fix:
===
Backport Bug#11756194 to mysql-5.5. slave breaks if
'drop database' fails on master and mismatched tables on
slave.

'DROP TABLE <deleted tables>' was binlogged when
'DROP DATABASE' failed and at least one table was deleted
from the database. The log event would lead slave SQL thread
stop if some of the tables did not exist on slave.

After this patch, It is always binlogged with 'IF EXISTS'
option.
parent 901ce531
......@@ -31,12 +31,47 @@ source include/show_binlog_events.inc;
FLUSH STATUS;
--echo
--echo # 'DROP TABLE IF EXISTS <deleted tables>' is binlogged
--echo # when 'DROP DATABASE' fails and at least one table is deleted
--echo # from the database.
RESET MASTER;
CREATE DATABASE testing_1;
USE testing_1;
CREATE TABLE t1(c1 INT);
CREATE TABLE t2(c1 INT);
let $prefix= `SELECT UUID()`;
--echo # Create a file in the database directory
--replace_result $prefix FAKE_FILE
eval SELECT 'hello' INTO OUTFILE 'fake_file.$prefix';
--echo
--echo # 'DROP DATABASE' will fail if there is any other file in the the
--echo # database directory
# Use '/' instead of '\' in the error message. On windows platform, dir is
# formed with '\'.
--replace_regex /\\testing_1\\*/\/testing_1\//
--error 1010
DROP DATABASE testing_1;
let $wait_binlog_event= DROP TABLE IF EXIST;
source include/wait_for_binlog_event.inc;
let $MYSQLD_DATADIR= `SELECT @@datadir`;
--echo
--echo # Remove the fake file.
--remove_file $MYSQLD_DATADIR/testing_1/fake_file.$prefix
--echo # Now we can drop the database.
DROP DATABASE testing_1;
--echo #
--echo # Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
--echo # BASED REPLICATION
--echo #
USE test;
--disable_warnings
DROP DATABASE IF EXISTS db1;
DROP TABLE IF EXISTS t3;
......
......@@ -39,10 +39,31 @@ 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 TABLE `t1` /* generated by server */
FLUSH STATUS;
# 'DROP TABLE IF EXISTS <deleted tables>' is binlogged
# when 'DROP DATABASE' fails and at least one table is deleted
# from the database.
RESET MASTER;
CREATE DATABASE testing_1;
USE testing_1;
CREATE TABLE t1(c1 INT);
CREATE TABLE t2(c1 INT);
# Create a file in the database directory
SELECT 'hello' INTO OUTFILE 'fake_file.FAKE_FILE';
# 'DROP DATABASE' will fail if there is any other file in the the
# database directory
DROP DATABASE testing_1;
ERROR HY000: Error dropping database (can't rmdir './testing_1/', errno: 17)
# Remove the fake file.
# Now we can drop the database.
DROP DATABASE testing_1;
#
# Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
# BASED REPLICATION
#
USE test;
DROP DATABASE IF EXISTS db1;
DROP TABLE IF EXISTS t3;
CREATE DATABASE db1;
......@@ -58,7 +79,7 @@ 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`
master-bin.000001 # Query # # use `db1`; DROP TABLE IF EXISTS `t1`
DROP TABLE t3;
DROP DATABASE db1;
set binlog_format=mixed;
......@@ -102,10 +123,31 @@ 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 TABLE `t1` /* generated by server */
FLUSH STATUS;
# 'DROP TABLE IF EXISTS <deleted tables>' is binlogged
# when 'DROP DATABASE' fails and at least one table is deleted
# from the database.
RESET MASTER;
CREATE DATABASE testing_1;
USE testing_1;
CREATE TABLE t1(c1 INT);
CREATE TABLE t2(c1 INT);
# Create a file in the database directory
SELECT 'hello' INTO OUTFILE 'fake_file.FAKE_FILE';
# 'DROP DATABASE' will fail if there is any other file in the the
# database directory
DROP DATABASE testing_1;
ERROR HY000: Error dropping database (can't rmdir './testing_1/', errno: 17)
# Remove the fake file.
# Now we can drop the database.
DROP DATABASE testing_1;
#
# Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
# BASED REPLICATION
#
USE test;
DROP DATABASE IF EXISTS db1;
DROP TABLE IF EXISTS t3;
CREATE DATABASE db1;
......@@ -121,7 +163,7 @@ 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`
master-bin.000001 # Query # # use `db1`; DROP TABLE IF EXISTS `t1`
DROP TABLE t3;
DROP DATABASE db1;
set binlog_format=row;
......@@ -166,10 +208,31 @@ master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # DROP TEMPORARY TABLE IF EXISTS `test`.`tt1` /* generated by server */
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
FLUSH STATUS;
# 'DROP TABLE IF EXISTS <deleted tables>' is binlogged
# when 'DROP DATABASE' fails and at least one table is deleted
# from the database.
RESET MASTER;
CREATE DATABASE testing_1;
USE testing_1;
CREATE TABLE t1(c1 INT);
CREATE TABLE t2(c1 INT);
# Create a file in the database directory
SELECT 'hello' INTO OUTFILE 'fake_file.FAKE_FILE';
# 'DROP DATABASE' will fail if there is any other file in the the
# database directory
DROP DATABASE testing_1;
ERROR HY000: Error dropping database (can't rmdir './testing_1/', errno: 17)
# Remove the fake file.
# Now we can drop the database.
DROP DATABASE testing_1;
#
# Bug#11765416 58381: FAILED DROP DATABASE CAN BREAK STATEMENT
# BASED REPLICATION
#
USE test;
DROP DATABASE IF EXISTS db1;
DROP TABLE IF EXISTS t3;
CREATE DATABASE db1;
......@@ -185,7 +248,7 @@ 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`
master-bin.000001 # Query # # use `db1`; DROP TABLE IF EXISTS `t1`
DROP TABLE t3;
DROP DATABASE db1;
show databases;
......
include/master-slave.inc
[connection master]
CREATE DATABASE IF NOT EXISTS db1;
CREATE DATABASE IF NOT EXISTS db2;
use db1;
CREATE TABLE a(id INT);
CREATE VIEW v AS SELECT * FROM a;
CREATE TABLE table_father(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20)) ENGINE=INNODB;
use db2;
CREATE TABLE table_child(id INT PRIMARY KEY, info VARCHAR(20), father_id INT) ENGINE=INNODB;
ALTER TABLE table_child ADD CONSTRAINT aaa FOREIGN KEY (father_id) REFERENCES db1.table_father(id);
DROP DATABASE db1;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
DROP DATABASE db2;
DROP DATABASE db1;
include/rpl_end.inc
###############################################################################
# Bug#20041860: SLAVE ERROR WHEN DROP DATABASE
#
# Test:
# =====
# Create two databases such that one database has a dependency over the other
# database and try to drop the database which has a dependency. This should
# not cause slave to break.
###############################################################################
--source include/master-slave.inc
connection master;
CREATE DATABASE IF NOT EXISTS db1;
CREATE DATABASE IF NOT EXISTS db2;
use db1;
CREATE TABLE a(id INT);
CREATE VIEW v AS SELECT * FROM a;
CREATE TABLE table_father(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20)) ENGINE=INNODB;
use db2;
CREATE TABLE table_child(id INT PRIMARY KEY, info VARCHAR(20), father_id INT) ENGINE=INNODB;
ALTER TABLE table_child ADD CONSTRAINT aaa FOREIGN KEY (father_id) REFERENCES db1.table_father(id);
--error ER_ROW_IS_REFERENCED
DROP DATABASE db1;
DROP DATABASE db2;
--sync_slave_with_master
--connection master
DROP DATABASE db1;
--source include/rpl_end.inc
/*
Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
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
......@@ -942,7 +942,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN)))
goto exit; /* not much else we can do */
query_pos= query_data_start= strmov(query,"DROP TABLE ");
query_pos= query_data_start= strmov(query,"DROP TABLE IF EXISTS ");
query_end= query + MAX_DROP_TABLE_Q_LEN;
db_len= strlen(db);
......
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