diff --git a/mysql-test/suite/rpl/r/rpl_savepoint.result b/mysql-test/suite/rpl/r/rpl_savepoint.result new file mode 100644 index 00000000000..e1462f435a3 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_savepoint.result @@ -0,0 +1,32 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +# +# Bug#50124 Rpl failure on DROP table with concurrent txn/non-txn +# DML flow and SAVEPOINT +# +# Connection master +DROP TABLE IF EXISTS tt, nt; +CREATE TABLE tt (i INT) ENGINE = InnoDB; +CREATE TABLE nt (i INT) ENGINE = MyISAM; +FLUSH LOGS; +START TRANSACTION; +INSERT INTO nt VALUES (1); +SAVEPOINT insert_statement; +INSERT INTO tt VALUES (1); +# Connection master1 +# Sending: +DROP TABLE tt; +# Connection master +ROLLBACK TO SAVEPOINT insert_statement; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +COMMIT; +# Connection master1 +# Reaping: DROP TABLE tt +FLUSH LOGS; +# Connection master +DROP TABLE nt; diff --git a/mysql-test/suite/rpl/t/rpl_savepoint.test b/mysql-test/suite/rpl/t/rpl_savepoint.test new file mode 100644 index 00000000000..c3d1f44d162 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_savepoint.test @@ -0,0 +1,47 @@ +--source include/master-slave.inc +--source include/have_innodb.inc + +--echo # +--echo # Bug#50124 Rpl failure on DROP table with concurrent txn/non-txn +--echo # DML flow and SAVEPOINT +--echo # + +--echo # Connection master +connection master; + +--disable_warnings +DROP TABLE IF EXISTS tt, nt; +--enable_warnings + +CREATE TABLE tt (i INT) ENGINE = InnoDB; +CREATE TABLE nt (i INT) ENGINE = MyISAM; +FLUSH LOGS; +START TRANSACTION; +INSERT INTO nt VALUES (1); +SAVEPOINT insert_statement; +INSERT INTO tt VALUES (1); + +--echo # Connection master1 +connection master1; +--echo # Sending: +--send DROP TABLE tt + +--echo # Connection master +connection master; +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table" AND info = "DROP TABLE tt"; +--source include/wait_condition.inc +ROLLBACK TO SAVEPOINT insert_statement; +COMMIT; + +--echo # Connection master1 +connection master1; +--echo # Reaping: DROP TABLE tt +--reap +FLUSH LOGS; + +--echo # Connection master +connection master; +DROP TABLE nt; +--source include/master-slave-end.inc diff --git a/sql/transaction.cc b/sql/transaction.cc index 78551d6fcf7..f6786f20dcf 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -419,9 +419,13 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name) thd->transaction.savepoints= sv; /* - Release metadata locks that were acquired during this savepoint unit. + Release metadata locks that were acquired during this savepoint unit + unless binlogging is on. Releasing locks with binlogging on can break + replication as it allows other connections to drop these tables before + rollback to savepoint is written to the binlog. */ - if (!res) + bool binlog_on= mysql_bin_log.is_open() && thd->variables.sql_log_bin; + if (!res && !binlog_on) thd->mdl_context.rollback_to_savepoint(sv->mdl_savepoint); DBUG_RETURN(test(res));