diff options
author | unknown <Li-Bing.Song@sun.com> | 2010-10-16 22:20:35 +0800 |
---|---|---|
committer | unknown <Li-Bing.Song@sun.com> | 2010-10-16 22:20:35 +0800 |
commit | c20cbe5b4af9fc4735fb5d4a6b15ddfcb20ae37d (patch) | |
tree | 2a64770661183d8337ae0e746f0b197e5bcac1e7 | |
parent | 650e4c25db94273bdf2300ddb987294f0d4edd72 (diff) | |
parent | 211552ccee98e381a14dfaae754528d9f6ed0494 (diff) | |
download | mariadb-git-c20cbe5b4af9fc4735fb5d4a6b15ddfcb20ae37d.tar.gz |
Manual merge
-rw-r--r-- | mysql-test/extra/rpl_tests/rpl_stop_slave.test | 61 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_stop_slave.result | 77 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_stop_slave.test | 51 | ||||
-rw-r--r-- | sql/slave.cc | 12 | ||||
-rw-r--r-- | sql/sql_parse.cc | 9 |
5 files changed, 209 insertions, 1 deletions
diff --git a/mysql-test/extra/rpl_tests/rpl_stop_slave.test b/mysql-test/extra/rpl_tests/rpl_stop_slave.test new file mode 100644 index 00000000000..7c88afe3532 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_stop_slave.test @@ -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; diff --git a/mysql-test/suite/rpl/r/rpl_stop_slave.result b/mysql-test/suite/rpl/r/rpl_stop_slave.result new file mode 100644 index 00000000000..37870f3e028 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_stop_slave.result @@ -0,0 +1,77 @@ +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 ... 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; + +# Test end +SET GLOBAL debug= '$debug_save'; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/rpl/t/rpl_stop_slave.test b/mysql-test/suite/rpl/t/rpl_stop_slave.test new file mode 100644 index 00000000000..3950b59908a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stop_slave.test @@ -0,0 +1,51 @@ +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 ... 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; + +# Don't need to verify 'CREATE TEMPORARY TABLE' with MyIASM engine, as it +# never is binlogged into a transaction since 5.5. + +--echo +--echo # Test end +SET GLOBAL debug= '$debug_save'; + +connection master; +DROP TABLE t1, t2; +source include/master-slave-end.inc; diff --git a/sql/slave.cc b/sql/slave.cc index 677199bfc0e..ab8952069fb 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -881,7 +881,17 @@ static bool sql_slave_killed(THD* thd, Relay_log_info* rli) 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 " diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2f8a72ee25c..d308e1c7648 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2832,6 +2832,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: |