Hi Libing,
Nice work. Please address Luis's comments.
Patch approved!
Best Regards,
Daogang
Li-Bing.Song@stripped wrote:
> #At file:///home/anders/work/bzrwork/worktree3/mysql-5.1-rep%2B2/ based on
> revid:li-bing.song@stripped
>
> 3185 Li-Bing.Song@stripped 2010-05-06
> Bug #48084 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.
>
> modified:
> mysql-test/extra/binlog_tests/database.test
> mysql-test/suite/binlog/r/binlog_database.result
> sql/sql_db.cc
> === modified file 'mysql-test/extra/binlog_tests/database.test'
> --- a/mysql-test/extra/binlog_tests/database.test 2009-01-23 12:22:05 +0000
> +++ b/mysql-test/extra/binlog_tests/database.test 2010-05-06 06:56:36 +0000
> @@ -30,3 +30,32 @@ drop table tt1, t1;
> 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
> +--error 1010
> +DROP DATABASE testing_1;
> +source include/show_binlog_events.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;
>
> === modified file 'mysql-test/suite/binlog/r/binlog_database.result'
> --- a/mysql-test/suite/binlog/r/binlog_database.result 2009-11-03 19:02:56 +0000
> +++ b/mysql-test/suite/binlog/r/binlog_database.result 2010-05-06 06:56:36 +0000
> @@ -38,6 +38,32 @@ master-bin.000001 # Query # # use `test`
> master-bin.000001 # Query # # COMMIT
> master-bin.000001 # Query # # use `test`; drop table tt1, t1
> 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)
> +show binlog events from <binlog_start>;
> +Log_name Pos Event_type Server_id End_log_pos Info
> +master-bin.000001 # Query # # CREATE DATABASE testing_1
> +master-bin.000001 # Query # # use `testing_1`; CREATE TABLE t1(c1 INT)
> +master-bin.000001 # Query # # use `testing_1`; CREATE TABLE t2(c1 INT)
> +master-bin.000001 # Query # # use `testing_1`; DROP TABLE IF EXISTS `t2`,`t1`
> +
> +# Remove the fake file.
> +# Now we can drop the database.
> +DROP DATABASE testing_1;
> set binlog_format=mixed;
> reset master;
> create database testing_1;
> @@ -78,6 +104,32 @@ master-bin.000001 # Query # # use `test`
> master-bin.000001 # Query # # COMMIT
> master-bin.000001 # Query # # use `test`; drop table tt1, t1
> 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)
> +show binlog events from <binlog_start>;
> +Log_name Pos Event_type Server_id End_log_pos Info
> +master-bin.000001 # Query # # CREATE DATABASE testing_1
> +master-bin.000001 # Query # # use `testing_1`; CREATE TABLE t1(c1 INT)
> +master-bin.000001 # Query # # use `testing_1`; CREATE TABLE t2(c1 INT)
> +master-bin.000001 # Query # # use `testing_1`; DROP TABLE IF EXISTS `t2`,`t1`
> +
> +# Remove the fake file.
> +# Now we can drop the database.
> +DROP DATABASE testing_1;
> set binlog_format=row;
> reset master;
> create database testing_1;
> @@ -119,6 +171,32 @@ master-bin.000001 # Write_rows # # table
> master-bin.000001 # Query # # COMMIT
> 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)
> +show binlog events from <binlog_start>;
> +Log_name Pos Event_type Server_id End_log_pos Info
> +master-bin.000001 # Query # # CREATE DATABASE testing_1
> +master-bin.000001 # Query # # use `testing_1`; CREATE TABLE t1(c1 INT)
> +master-bin.000001 # Query # # use `testing_1`; CREATE TABLE t2(c1 INT)
> +master-bin.000001 # Query # # use `testing_1`; DROP TABLE IF EXISTS `t2`,`t1`
> +
> +# Remove the fake file.
> +# Now we can drop the database.
> +DROP DATABASE testing_1;
> show databases;
> Database
> information_schema
>
> === modified file 'sql/sql_db.cc'
> --- a/sql/sql_db.cc 2010-02-12 23:30:44 +0000
> +++ b/sql/sql_db.cc 2010-05-06 06:56:36 +0000
> @@ -998,7 +998,7 @@ bool mysql_rm_db(THD *thd,char *db,bool
>
> 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);
>
>
>
> ------------------------------------------------------------------------
>
>