Commit 8805fda0 authored by Mats Kindahl's avatar Mats Kindahl

Bug #38773: DROP DATABASE cause switch to stmt-mode when there are temporary tables open

When executing a DROP DATABASE statement in ROW mode and having temporary
tables open at the same time, the existance of temporary tables prevent
the server from switching back to row mode after temporarily switching to
statement mode to handle the logging of the statement.

Fixed the problem by removing the code to switch to statement mode and added
code to temporarily disable the binary log while dropping the objects in the
database.

mysql-test/extra/binlog_tests/database.test:
  Added test to ensure that DROP DATABASE does not affect the replication mode.
mysql-test/suite/binlog/r/binlog_database.result:
  Result file change.
sql/sql_db.cc:
  Removed code that clears the current_stmt_binlog_row_based flag.
  Added code to disable the binary log while dropping the objects
  in a database.
parent dad230ab
......@@ -13,3 +13,18 @@ create trigger tr1 before insert on t1 for each row insert into t2 values (2*new
create procedure sp1 (a int) insert into t1 values(a);
drop database testing_1;
source include/show_binlog_events.inc;
# BUG#38773: DROP DATABASE cause switch to stmt-mode when there are
# temporary tables open
use test;
reset master;
create temporary table tt1 (a int);
create table t1 (a int);
insert into t1 values (1);
disable_warnings;
drop database if exists mysqltest1;
enable_warnings;
insert into t1 values (1);
drop table tt1, t1;
source include/show_binlog_events.inc;
......@@ -17,6 +17,22 @@ master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost`
master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`(a int)
insert into t1 values(a)
master-bin.000001 # Query # # drop database testing_1
use test;
reset master;
create temporary table tt1 (a int);
create table t1 (a int);
insert into t1 values (1);
drop database if exists mysqltest1;
insert into t1 values (1);
drop table tt1, t1;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; create temporary table tt1 (a int)
master-bin.000001 # Query # # use `test`; create table t1 (a int)
master-bin.000001 # Query # # use `test`; insert into t1 values (1)
master-bin.000001 # Query # # drop database if exists mysqltest1
master-bin.000001 # Query # # use `test`; insert into t1 values (1)
master-bin.000001 # Query # # use `test`; drop table tt1, t1
set binlog_format=mixed;
reset master;
create database testing_1;
......@@ -36,6 +52,22 @@ master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost`
master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`(a int)
insert into t1 values(a)
master-bin.000001 # Query # # drop database testing_1
use test;
reset master;
create temporary table tt1 (a int);
create table t1 (a int);
insert into t1 values (1);
drop database if exists mysqltest1;
insert into t1 values (1);
drop table tt1, t1;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; create temporary table tt1 (a int)
master-bin.000001 # Query # # use `test`; create table t1 (a int)
master-bin.000001 # Query # # use `test`; insert into t1 values (1)
master-bin.000001 # Query # # drop database if exists mysqltest1
master-bin.000001 # Query # # use `test`; insert into t1 values (1)
master-bin.000001 # Query # # use `test`; drop table tt1, t1
set binlog_format=row;
reset master;
create database testing_1;
......@@ -55,6 +87,27 @@ master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost`
master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` PROCEDURE `sp1`(a int)
insert into t1 values(a)
master-bin.000001 # Query # # drop database testing_1
use test;
reset master;
create temporary table tt1 (a int);
create table t1 (a int);
insert into t1 values (1);
drop database if exists mysqltest1;
insert into t1 values (1);
drop table tt1, t1;
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; create table t1 (a int)
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # drop database if exists mysqltest1
master-bin.000001 # Query # # use `test`; BEGIN
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # use `test`; COMMIT
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
show databases;
Database
information_schema
......
......@@ -883,13 +883,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
thd->clear_current_stmt_binlog_row_based();
length= build_table_filename(path, sizeof(path), db, "", "", 0);
strmov(path+length, MY_DB_OPT_FILE); // Append db option file name
del_dbopt(path); // Remove dboption hash entry
......@@ -914,8 +907,21 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
remove_db_from_cache(db);
pthread_mutex_unlock(&LOCK_open);
error= -1;
/*
We temporarily disable the binary log while dropping the objects
in the database. Since the DROP DATABASE statement is always
replicated as a statement, execution of it will drop all objects
in the database on the slave as well, so there is no need to
replicate the removal of the individual objects in the database
as well.
This is more of a safety precaution, since normally no objects
should be dropped while the database is being cleaned, but in
the event that a change in the code to remove other objects is
made, these drops should still not be logged.
*/
tmp_disable_binlog(thd);
if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0,
&dropped_tables)) >= 0)
{
......@@ -927,6 +933,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
#endif
error = 0;
}
reenable_binlog(thd);
}
if (!silent && deleted>=0)
{
......
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