source include/have_semisync_plugin.inc; source include/not_embedded.inc; source include/have_innodb.inc; source include/master-slave.inc; let $engine_type= InnoDB; #let $engine_type= MyISAM; # Suppress warnings that might be generated during the test disable_query_log; connection master; call mtr.add_suppression("Timeout waiting for reply of binlog"); call mtr.add_suppression("Read semi-sync reply"); call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); connection slave; call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Semi-sync slave .* reply"); enable_query_log; connection master; # After fix of BUG#45848, semi-sync slave should not create any extra # connections on master, save the count of connections before start # semi-sync slave for comparison below. let $_connections_normal_slave= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1); --echo # --echo # Uninstall semi-sync plugins on master and slave --echo # connection slave; disable_query_log; source include/stop_slave.inc; reset slave; disable_warnings; error 0,1305; UNINSTALL PLUGIN rpl_semi_sync_slave; error 0,1305; UNINSTALL PLUGIN rpl_semi_sync_master; enable_warnings; connection master; reset master; set sql_log_bin=0; disable_warnings; error 0,1305; UNINSTALL PLUGIN rpl_semi_sync_slave; error 0,1305; UNINSTALL PLUGIN rpl_semi_sync_master; enable_warnings; set sql_log_bin=1; enable_query_log; --echo # --echo # Main test of semi-sync replication start here --echo # connection master; echo [ on master ]; disable_query_log; let $value = query_get_value(show variables like 'rpl_semi_sync_master_enabled', Value, 1); if (`select '$value' = 'No such row'`) { set sql_log_bin=0; eval INSTALL PLUGIN rpl_semi_sync_master SONAME '$SEMISYNC_MASTER_PLUGIN'; set global rpl_semi_sync_master_timeout= 5000; /* 5s */ set sql_log_bin=1; } enable_query_log; echo [ default state of semi-sync on master should be OFF ]; show variables like 'rpl_semi_sync_master_enabled'; echo [ enable semi-sync on master ]; set global rpl_semi_sync_master_enabled = 1; show variables like 'rpl_semi_sync_master_enabled'; echo [ status of semi-sync on master should be ON even without any semi-sync slaves ]; show status like 'Rpl_semi_sync_master_clients'; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_yes_tx'; --echo # --echo # BUG#45672 Semisync repl: ActiveTranx:insert_tranx_node: transaction node allocation failed --echo # BUG#45673 Semisynch reports correct operation even if no slave is connected --echo # # BUG#45672 When semi-sync is enabled on master, it would allocate # transaction node even without semi-sync slave connected, and would # finally result in transaction node allocation error. # # Semi-sync master will pre-allocate 'max_connections' transaction # nodes, so here we do more than that much transactions to check if it # will fail or not. # select @@global.max_connections + 1; let $i= `select @@global.max_connections + 1`; disable_query_log; eval create table t1 (a int) engine=$engine_type; while ($i) { eval insert into t1 values ($i); dec $i; } drop table t1; enable_query_log; # BUG#45673 echo [ status of semi-sync on master should be OFF ]; show status like 'Rpl_semi_sync_master_clients'; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_yes_tx'; disable_query_log; # reset master to make sure the following test will start with a clean environment reset master; enable_query_log; --echo # --echo # INSTALL PLUGIN semi-sync on slave --echo # connection slave; echo [ on slave ]; disable_query_log; let $value= query_get_value(show variables like 'rpl_semi_sync_slave_enabled', Value, 1); if (`select '$value' = 'No such row'`) { set sql_log_bin=0; eval INSTALL PLUGIN rpl_semi_sync_slave SONAME '$SEMISYNC_SLAVE_PLUGIN'; set sql_log_bin=1; } enable_query_log; echo [ default state of semi-sync on slave should be OFF ]; show variables like 'rpl_semi_sync_slave_enabled'; echo [ enable semi-sync on slave ]; set global rpl_semi_sync_slave_enabled = 1; show variables like 'rpl_semi_sync_slave_enabled'; source include/start_slave.inc; connection master; echo [ on master ]; # NOTE: Rpl_semi_sync_master_client will only be updated when # semi-sync slave has started binlog dump request let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 1; source include/wait_for_status_var.inc; echo [ initial master state after the semi-sync slave connected ]; show status like 'Rpl_semi_sync_master_clients'; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; replace_result $engine_type ENGINE_TYPE; eval create table t1(a int) engine = $engine_type; echo [ master state after CREATE TABLE statement ]; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; # After fix of BUG#45848, semi-sync slave should not create any extra # connections on master. let $_connections_semisync_slave= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1); replace_result $_connections_semisync_slave CONNECTIONS_SEMISYNC_SLAVE; replace_result $_connections_normal_slave CONNECTIONS_NORMAL_SLAVE; eval select $_connections_semisync_slave - $_connections_normal_slave as 'Should be 0'; let $i=300; echo [ insert records to table ]; disable_query_log; while ($i) { eval insert into t1 values ($i); dec $i; } enable_query_log; echo [ master status after inserts ]; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; sync_slave_with_master; echo [ on slave ]; echo [ slave status after replicated inserts ]; show status like 'Rpl_semi_sync_slave_status'; select count(distinct a) from t1; select min(a) from t1; select max(a) from t1; --echo --echo # BUG#50157 --echo # semi-sync replication crashes when replicating a transaction which --echo # include 'CREATE TEMPORARY TABLE `MyISAM_t` SELECT * FROM `Innodb_t` ; connection master; echo [ on master ]; SET SESSION AUTOCOMMIT= 0; CREATE TABLE t2(c1 INT) ENGINE=innodb; sync_slave_with_master; connection master; BEGIN; --echo --echo # Even though it is in a transaction, this statement is binlogged into binlog --echo # file immediately. --disable_warnings CREATE TEMPORARY TABLE t3 SELECT c1 FROM t2 where 1=1; --enable_warnings --echo --echo # These statements will not be binlogged until the transaction is committed INSERT INTO t2 VALUES(11); INSERT INTO t2 VALUES(22); COMMIT; DROP TABLE t2, t3; SET SESSION AUTOCOMMIT= 1; sync_slave_with_master; --echo # --echo # Test semi-sync master will switch OFF after one transaction --echo # timeout waiting for slave reply. --echo # connection slave; source include/stop_slave.inc; connection master; echo [ on master ]; # The first semi-sync check should be on because after slave stop, # there are no transactions on the master. echo [ master status should be ON ]; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; show status like 'Rpl_semi_sync_master_clients'; echo [ semi-sync replication of these transactions will fail ]; insert into t1 values (500); # Wait for the semi-sync replication of this transaction to timeout let $status_var= Rpl_semi_sync_master_status; let $status_var_value= OFF; source include/wait_for_status_var.inc; # The second semi-sync check should be off because one transaction # times out during waiting. echo [ master status should be OFF ]; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; # Semi-sync status on master is now OFF, so all these transactions # will be replicated asynchronously. let $i=300; disable_query_log; while ($i) { eval delete from t1 where a=$i; dec $i; } enable_query_log; insert into t1 values (100); echo [ master status should be OFF ]; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; --echo # --echo # Test semi-sync status on master will be ON again when slave catches up --echo # # Save the master position for later use. save_master_pos; connection slave; echo [ on slave ]; echo [ slave status should be OFF ]; show status like 'Rpl_semi_sync_slave_status'; source include/start_slave.inc; sync_with_master; echo [ slave status should be ON ]; show status like 'Rpl_semi_sync_slave_status'; select count(distinct a) from t1; select min(a) from t1; select max(a) from t1; connection master; echo [ on master ]; # The master semi-sync status should be on again after slave catches up. echo [ master status should be ON again after slave catches up ]; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; show status like 'Rpl_semi_sync_master_clients'; --echo # --echo # Test disable/enable master semi-sync on the fly. --echo # drop table t1; sync_slave_with_master; echo [ on slave ]; source include/stop_slave.inc; --echo # --echo # Flush status --echo # connection master; echo [ Semi-sync master status variables before FLUSH STATUS ]; SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx'; SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx'; # Do not write the FLUSH STATUS to binlog, to make sure we'll get a # clean status after this. FLUSH NO_WRITE_TO_BINLOG STATUS; echo [ Semi-sync master status variables after FLUSH STATUS ]; SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx'; SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx'; connection master; echo [ on master ]; source include/show_master_logs.inc; show variables like 'rpl_semi_sync_master_enabled'; echo [ disable semi-sync on the fly ]; set global rpl_semi_sync_master_enabled=0; show variables like 'rpl_semi_sync_master_enabled'; show status like 'Rpl_semi_sync_master_status'; echo [ enable semi-sync on the fly ]; set global rpl_semi_sync_master_enabled=1; show variables like 'rpl_semi_sync_master_enabled'; show status like 'Rpl_semi_sync_master_status'; --echo # --echo # Test RESET MASTER/SLAVE --echo # connection slave; echo [ on slave ]; source include/start_slave.inc; connection master; echo [ on master ]; replace_result $engine_type ENGINE_TYPE; eval create table t1 (a int) engine = $engine_type; drop table t1; ##show status like 'Rpl_semi_sync_master_status'; sync_slave_with_master; --replace_column 2 # show status like 'Rpl_relay%'; echo [ test reset master ]; connection master; echo [ on master]; reset master; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; connection slave; echo [ on slave ]; source include/stop_slave.inc; reset slave; # Kill the dump thread on master for previous slave connection and # wait for it to exit connection master; let $_tid= `select id from information_schema.processlist where command = 'Binlog Dump' limit 1`; if ($_tid) { disable_query_log; eval kill query $_tid; enable_query_log; # After dump thread exit, Rpl_semi_sync_master_clients will be 0 let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 0; source include/wait_for_status_var.inc; } connection slave; source include/start_slave.inc; connection master; echo [ on master ]; # Wait for dump thread to start, Rpl_semi_sync_master_clients will be # 1 after dump thread started. let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 1; source include/wait_for_status_var.inc; replace_result $engine_type ENGINE_TYPE; eval create table t1 (a int) engine = $engine_type; insert into t1 values (1); insert into t1 values (2), (3); sync_slave_with_master; echo [ on slave ]; select * from t1; connection master; echo [ on master ]; echo [ master semi-sync status should be ON ]; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; --echo # --echo # Start semi-sync replication without SUPER privilege --echo # connection slave; source include/stop_slave.inc; reset slave; connection master; echo [ on master ]; reset master; # Kill the dump thread on master for previous slave connection and wait for it to exit let $_tid= `select id from information_schema.processlist where command = 'Binlog Dump' limit 1`; if ($_tid) { disable_query_log; eval kill query $_tid; enable_query_log; # After dump thread exit, Rpl_semi_sync_master_clients will be 0 let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 0; source include/wait_for_status_var.inc; } # Do not binlog the following statement because it will generate # different events for ROW and STATEMENT format set sql_log_bin=0; grant replication slave on *.* to rpl@127.0.0.1 identified by 'rpl'; flush privileges; set sql_log_bin=1; connection slave; echo [ on slave ]; grant replication slave on *.* to rpl@127.0.0.1 identified by 'rpl'; flush privileges; change master to master_user='rpl',master_password='rpl'; source include/start_slave.inc; show status like 'Rpl_semi_sync_slave_status'; connection master; echo [ on master ]; # Wait for the semi-sync binlog dump thread to start let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 1; source include/wait_for_status_var.inc; echo [ master semi-sync should be ON ]; show status like 'Rpl_semi_sync_master_clients'; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; insert into t1 values (4); insert into t1 values (5); echo [ master semi-sync should be ON ]; show status like 'Rpl_semi_sync_master_clients'; show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; --echo # --echo # Test semi-sync slave connect to non-semi-sync master --echo # # Disable semi-sync on master connection slave; echo [ on slave ]; source include/stop_slave.inc; SHOW STATUS LIKE 'Rpl_semi_sync_slave_status'; connection master; echo [ on master ]; # Kill the dump thread on master for previous slave connection and wait for it to exit let $_tid= `select id from information_schema.processlist where command = 'Binlog Dump' limit 1`; if ($_tid) { disable_query_log; eval kill query $_tid; enable_query_log; # After dump thread exit, Rpl_semi_sync_master_clients will be 0 let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 0; source include/wait_for_status_var.inc; } echo [ Semi-sync status on master should be ON ]; show status like 'Rpl_semi_sync_master_clients'; show status like 'Rpl_semi_sync_master_status'; set global rpl_semi_sync_master_enabled= 0; connection slave; echo [ on slave ]; SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled'; source include/start_slave.inc; connection master; echo [ on master ]; insert into t1 values (8); let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 1; source include/wait_for_status_var.inc; echo [ master semi-sync clients should be 1, status should be OFF ]; show status like 'Rpl_semi_sync_master_clients'; show status like 'Rpl_semi_sync_master_status'; sync_slave_with_master; echo [ on slave ]; show status like 'Rpl_semi_sync_slave_status'; # Uninstall semi-sync plugin on master connection slave; source include/stop_slave.inc; connection master; echo [ on master ]; set sql_log_bin=0; UNINSTALL PLUGIN rpl_semi_sync_master; set sql_log_bin=1; enable_query_log; SHOW VARIABLES LIKE 'rpl_semi_sync_master_enabled'; connection slave; echo [ on slave ]; SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled'; source include/start_slave.inc; connection master; echo [ on master ]; insert into t1 values (10); sync_slave_with_master; echo [ on slave ]; SHOW STATUS LIKE 'Rpl_semi_sync_slave_status'; --echo # --echo # Test non-semi-sync slave connect to semi-sync master --echo # connection master; set sql_log_bin=0; replace_result $SEMISYNC_MASTER_PLUGIN SEMISYNC_MASTER_PLUGIN; eval INSTALL PLUGIN rpl_semi_sync_master SONAME '$SEMISYNC_MASTER_PLUGIN'; set global rpl_semi_sync_master_timeout= 5000; /* 5s */ set sql_log_bin=1; set global rpl_semi_sync_master_enabled= 1; connection slave; echo [ on slave ]; source include/stop_slave.inc; SHOW STATUS LIKE 'Rpl_semi_sync_slave_status'; echo [ uninstall semi-sync slave plugin ]; UNINSTALL PLUGIN rpl_semi_sync_slave; SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled'; source include/start_slave.inc; SHOW STATUS LIKE 'Rpl_semi_sync_slave_status'; source include/stop_slave.inc; echo [ reinstall semi-sync slave plugin and disable semi-sync ]; replace_result $SEMISYNC_SLAVE_PLUGIN SEMISYNC_SLAVE_PLUGIN; eval INSTALL PLUGIN rpl_semi_sync_slave SONAME '$SEMISYNC_SLAVE_PLUGIN'; set global rpl_semi_sync_slave_enabled= 0; SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled'; SHOW STATUS LIKE 'Rpl_semi_sync_slave_status'; source include/start_slave.inc; SHOW STATUS LIKE 'Rpl_semi_sync_slave_status'; --echo # --echo # Clean up --echo # connection slave; source include/stop_slave.inc; UNINSTALL PLUGIN rpl_semi_sync_slave; connection master; UNINSTALL PLUGIN rpl_semi_sync_master; connection slave; source include/start_slave.inc; connection master; drop table t1; sync_slave_with_master; connection master; drop user rpl@127.0.0.1; flush privileges;