#At file:///home/anders/work/bzrwork1/wt5/mysql-trunk-merge/ based on revid:dmitry.shulga@stripped
3266 Li-Bing.Song@stripped 2010-10-13 [merge]
Auto merge
added:
mysql-test/extra/rpl_tests/rpl_stop_slave.test
mysql-test/suite/rpl/r/rpl_stop_slave.result
mysql-test/suite/rpl/t/rpl_stop_slave.test
modified:
sql/rpl_slave.cc
sql/sql_parse.cc
=== added file 'mysql-test/extra/rpl_tests/rpl_stop_slave.test'
--- a/mysql-test/extra/rpl_tests/rpl_stop_slave.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_stop_slave.test 2010-10-13 03:19:20 +0000
@@ -0,0 +1,61 @@
+#
+# Auxiliary file which is used to test BUG#56118
+#
+# Slave should apply all statements in the transaction before stop if any
+# temporary table is created or dropped.
+#
+# USEAGE:
+# --let $tmp_table_stm= a SQL statement
+# --source extra/rpl_tests/rpl_stop_slave.test
+#
+
+if (`SELECT "$tmp_table_stm" = ''`)
+{
+ --echo \$tmp_table_stm is NULL
+ --die $tmp_table_stm is NULL
+}
+
+--echo
+--echo [ On Master ]
+connection master;
+BEGIN;
+DELETE FROM t1;
+eval $tmp_table_stm;
+INSERT INTO t1 VALUES (1);
+DROP TEMPORARY TABLE tt1;
+COMMIT;
+
+--echo
+--echo [ On Slave ]
+connection slave;
+
+# To check if slave SQL thread is applying INSERT statement
+let $show_statement= SHOW PROCESSLIST;
+let $field= Info;
+let $condition= LIKE 'INSERT%';
+source include/wait_show_condition.inc;
+
+send STOP SLAVE SQL_THREAD;
+
+--echo
+--echo [ On Slave1 ]
+connection slave1;
+--echo # To resume slave SQL thread
+SET DEBUG_SYNC= 'now SIGNAL signal.continue';
+SET DEBUG_SYNC= 'RESET';
+
+--echo
+--echo [ On Slave ]
+connection slave;
+reap;
+source include/wait_for_slave_sql_to_stop.inc;
+
+--echo # Slave should stop after the transaction has committed.
+--echo # So t1 on master is same to t1 on slave.
+let diff_table_1=master:test.t1;
+let diff_table_2=slave:test.t1;
+source include/diff_tables.inc;
+
+connection slave;
+START SLAVE SQL_THREAD;
+source include/wait_for_slave_sql_to_start.inc;
=== added file 'mysql-test/suite/rpl/r/rpl_stop_slave.result'
--- a/mysql-test/suite/rpl/r/rpl_stop_slave.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_stop_slave.result 2010-10-13 03:19:20 +0000
@@ -0,0 +1,127 @@
+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#56118 STOP SLAVE does not wait till trx with CREATE TMP TABLE ends
+#
+# If a temporary table is created or dropped, the transaction should be
+# regarded similarly that a non-transactional table is modified. So
+# STOP SLAVE should wait until the transaction has finished.
+CREATE TABLE t1(c1 INT) ENGINE=InnoDB;
+CREATE TABLE t2(c1 INT) ENGINE=InnoDB;
+SET DEBUG_SYNC= 'RESET';
+include/stop_slave.inc
+
+# Suspend the INSERT statement in current transaction on SQL thread.
+# It guarantees that SQL thread is applying the transaction when
+# STOP SLAVE command launchs.
+SET GLOBAL debug= 'd,after_mysql_insert';
+include/start_slave.inc
+
+# CREATE TEMPORARY TABLE with InnoDB engine
+# -----------------------------------------
+
+[ On Master ]
+BEGIN;
+DELETE FROM t1;
+CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = InnoDB;
+INSERT INTO t1 VALUES (1);
+DROP TEMPORARY TABLE tt1;
+COMMIT;
+
+[ On Slave ]
+STOP SLAVE SQL_THREAD;
+
+[ On Slave1 ]
+# To resume slave SQL thread
+SET DEBUG_SYNC= 'now SIGNAL signal.continue';
+SET DEBUG_SYNC= 'RESET';
+
+[ On Slave ]
+# Slave should stop after the transaction has committed.
+# So t1 on master is same to t1 on slave.
+Comparing tables master:test.t1 and slave:test.t1
+START SLAVE SQL_THREAD;
+
+# CREATE TEMPORARY TABLE with MyISAM engine
+# -----------------------------------------
+
+[ On Master ]
+BEGIN;
+DELETE FROM t1;
+CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = MyISAM;
+INSERT INTO t1 VALUES (1);
+DROP TEMPORARY TABLE tt1;
+COMMIT;
+
+[ On Slave ]
+STOP SLAVE SQL_THREAD;
+
+[ On Slave1 ]
+# To resume slave SQL thread
+SET DEBUG_SYNC= 'now SIGNAL signal.continue';
+SET DEBUG_SYNC= 'RESET';
+
+[ On Slave ]
+# Slave should stop after the transaction has committed.
+# So t1 on master is same to t1 on slave.
+Comparing tables master:test.t1 and slave:test.t1
+START SLAVE SQL_THREAD;
+
+# CREATE TEMPORARY TABLE ... SELECT with InnoDB engine
+# ----------------------------------------------------
+
+[ On Master ]
+BEGIN;
+DELETE FROM t1;
+CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = InnoDB
+SELECT c1 FROM t2;
+INSERT INTO t1 VALUES (1);
+DROP TEMPORARY TABLE tt1;
+COMMIT;
+
+[ On Slave ]
+STOP SLAVE SQL_THREAD;
+
+[ On Slave1 ]
+# To resume slave SQL thread
+SET DEBUG_SYNC= 'now SIGNAL signal.continue';
+SET DEBUG_SYNC= 'RESET';
+
+[ On Slave ]
+# Slave should stop after the transaction has committed.
+# So t1 on master is same to t1 on slave.
+Comparing tables master:test.t1 and slave:test.t1
+START SLAVE SQL_THREAD;
+
+# CREATE TEMPORARY TABLE ... SELECT with MyISAM engine
+# ----------------------------------------------------
+
+[ On Master ]
+BEGIN;
+DELETE FROM t1;
+CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = MyISAM
+SELECT 1 AS c1;
+INSERT INTO t1 VALUES (1);
+DROP TEMPORARY TABLE tt1;
+COMMIT;
+
+[ On Slave ]
+STOP SLAVE SQL_THREAD;
+
+[ On Slave1 ]
+# To resume slave SQL thread
+SET DEBUG_SYNC= 'now SIGNAL signal.continue';
+SET DEBUG_SYNC= 'RESET';
+
+[ On Slave ]
+# Slave should stop after the transaction has committed.
+# So t1 on master is same to t1 on slave.
+Comparing tables master:test.t1 and slave:test.t1
+START SLAVE SQL_THREAD;
+# Test end
+SET GLOBAL debug= '$debug_save';
+DROP TABLE t1, t2;
=== added file 'mysql-test/suite/rpl/t/rpl_stop_slave.test'
--- a/mysql-test/suite/rpl/t/rpl_stop_slave.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_stop_slave.test 2010-10-13 03:19:20 +0000
@@ -0,0 +1,60 @@
+source include/master-slave.inc;
+source include/have_innodb.inc;
+source include/have_debug.inc;
+source include/have_debug_sync.inc;
+source include/have_binlog_format_mixed_or_statement.inc;
+
+--echo
+--echo # BUG#56118 STOP SLAVE does not wait till trx with CREATE TMP TABLE ends
+--echo #
+--echo # If a temporary table is created or dropped, the transaction should be
+--echo # regarded similarly that a non-transactional table is modified. So
+--echo # STOP SLAVE should wait until the transaction has finished.
+
+CREATE TABLE t1(c1 INT) ENGINE=InnoDB;
+CREATE TABLE t2(c1 INT) ENGINE=InnoDB;
+
+sync_slave_with_master;
+SET DEBUG_SYNC= 'RESET';
+source include/stop_slave.inc;
+
+--echo
+--echo # Suspend the INSERT statement in current transaction on SQL thread.
+--echo # It guarantees that SQL thread is applying the transaction when
+--echo # STOP SLAVE command launchs.
+let $debug_save= `SELECT @@GLOBAL.debug`;
+SET GLOBAL debug= 'd,after_mysql_insert';
+source include/start_slave.inc;
+
+--echo
+--echo # CREATE TEMPORARY TABLE with InnoDB engine
+--echo # -----------------------------------------
+let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = InnoDB;
+source extra/rpl_tests/rpl_stop_slave.test;
+
+--echo
+--echo # CREATE TEMPORARY TABLE with MyISAM engine
+--echo # -----------------------------------------
+let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = MyISAM;
+source extra/rpl_tests/rpl_stop_slave.test;
+
+--echo
+--echo # CREATE TEMPORARY TABLE ... SELECT with InnoDB engine
+--echo # ----------------------------------------------------
+let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = InnoDB
+ SELECT c1 FROM t2;
+source extra/rpl_tests/rpl_stop_slave.test;
+
+--echo
+--echo # CREATE TEMPORARY TABLE ... SELECT with MyISAM engine
+--echo # ----------------------------------------------------
+let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = MyISAM
+ SELECT 1 AS c1;
+source extra/rpl_tests/rpl_stop_slave.test;
+
+--echo # Test end
+SET GLOBAL debug= '$debug_save';
+
+connection master;
+DROP TABLE t1, t2;
+source include/master-slave-end.inc;
=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc 2010-10-09 10:25:01 +0000
+++ b/sql/rpl_slave.cc 2010-10-13 03:39:19 +0000
@@ -881,7 +881,17 @@ static bool sql_slave_killed(THD* thd, R
DBUG_ASSERT(rli->slave_running == 1);// tracking buffer overrun
if (abort_loop || thd->killed || rli->abort_slave)
{
- if (thd->transaction.all.modified_non_trans_table && rli->is_in_group())
+ /*
+ The transaction should always be binlogged if OPTION_KEEP_LOG is set
+ (it implies that something can not be rolled back). And such case
+ should be regarded similarly as modifing a non-transactional table
+ because retrying of the transaction will lead to an error or inconsistency
+ as well.
+ Example: OPTION_KEEP_LOG is set if a temporary table is created or dropped.
+ */
+ if ((thd->transaction.all.modified_non_trans_table ||
+ (thd->variables.option_bits & OPTION_KEEP_LOG))
+ && rli->is_in_group())
{
char msg_stopped[]=
"... The slave SQL is stopped, leaving the current group "
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-10-07 12:47:15 +0000
+++ b/sql/sql_parse.cc 2010-10-13 03:39:19 +0000
@@ -2824,6 +2824,15 @@ end_with_restore_list:
thd->first_successful_insert_id_in_cur_stmt=
thd->first_successful_insert_id_in_prev_stmt;
+ DBUG_EXECUTE_IF("after_mysql_insert",
+ {
+ const char act[]=
+ "now "
+ "wait_for signal.continue";
+ DBUG_ASSERT(opt_debug_sync_timeout > 0);
+ DBUG_ASSERT(!debug_sync_set_action(current_thd,
+ STRING_WITH_LEN(act)));
+ };);
break;
}
case SQLCOM_REPLACE_SELECT:
Attachment: [text/bzr-bundle] bzr/li-bing.song@sun.com-20101013033919-0eh1is177s9aild8.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk-merge branch (Li-Bing.Song:3266) | Li-Bing.Song | 13 Oct |