List:Commits« Previous MessageNext Message »
From:Jon Olav Hauglid Date:February 22 2011 2:02pm
Subject:bzr commit into mysql-5.5 branch (jon.hauglid:3353) Bug#11765416
View as plain text  
#At file:///export/home/x/mysql-5.5-bug11765416/ based on revid:jorgen.loland@stripped

 3353 Jon Olav Hauglid	2011-02-22
      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 mysqlbinlog.test.

    modified:
      mysql-test/r/mysqlbinlog.result
      mysql-test/t/mysqlbinlog.test
      sql/sql_db.cc
=== modified file 'mysql-test/r/mysqlbinlog.result'
--- a/mysql-test/r/mysqlbinlog.result	2010-12-29 05:22:52 +0000
+++ b/mysql-test/r/mysqlbinlog.result	2011-02-22 14:02:34 +0000
@@ -903,3 +903,26 @@ master-bin.000002	#	Query	#	#	CREATE DAT
 master-bin.000002	#	Query	#	#	use `test1`; CREATE TABLE t1(id int)
 master-bin.000002	#	Query	#	#	use `test1`; DROP TABLE `t1` /* generated by server */
 master-bin.000002	#	Query	#	#	DROP DATABASE test1
+USE test;
+#
+# 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;

=== modified file 'mysql-test/t/mysqlbinlog.test'
--- a/mysql-test/t/mysqlbinlog.test	2010-12-29 05:22:52 +0000
+++ b/mysql-test/t/mysqlbinlog.test	2011-02-22 14:02:34 +0000
@@ -526,4 +526,32 @@ exec $MYSQL_BINLOG $MYSQLD_DATADIR/$mast
 
 let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
 source include/show_binlog_events.inc;
+USE test;
+let $binlog_file=;
 
+
+--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;

=== modified file 'sql/sql_db.cc'
--- a/sql/sql_db.cc	2010-12-10 11:32:58 +0000
+++ b/sql/sql_db.cc	2011-02-22 14:02:34 +0000
@@ -833,12 +833,9 @@ bool mysql_rm_db(THD *thd,char *db,bool
   }
 
   thd->push_internal_handler(&err_handler);
-  if (thd->killed ||
-      (tables && mysql_rm_table_no_locks(thd, tables, true, false, true, true)))
-  {
-    tables= NULL;
-  }
-  else
+  if (!thd->killed &&
+      !(tables &&
+        mysql_rm_table_no_locks(thd, tables, true, false, true, true)))
   {
     /*
       We temporarily disable the binary log while dropping the objects
@@ -926,6 +923,7 @@ update_binlog:
   else if (mysql_bin_log.is_open())
   {
     char *query, *query_pos, *query_end, *query_data_start;
+    char buf[FN_REFLEN + 1];
     TABLE_LIST *tbl;
     uint db_len;
 
@@ -939,6 +937,12 @@ update_binlog:
     {
       uint tbl_name_len;
 
+      // Only write drop table to the binlog for tables that no longer exist.
+      build_table_filename(buf, sizeof(buf) - 1, tbl->db,
+                           tbl->table_name, reg_ext, 0);
+      if (access(buf, F_OK) == 0)
+        continue;
+
       /* 3 for the quotes and the comma*/
       tbl_name_len= strlen(tbl->table_name) + 3;
       if (query_pos + tbl_name_len + 1 >= query_end)


Attachment: [text/bzr-bundle] bzr/jon.hauglid@oracle.com-20110222140234-xnlglj4mhy49yyr3.bundle
Thread
bzr commit into mysql-5.5 branch (jon.hauglid:3353) Bug#11765416Jon Olav Hauglid22 Feb