# ==== Purpose ==== # # Verify that Seconds_Behind_Master is calculated correctly on a # Multi-threaded Slave when slave_parallel_type = 'LOGICAL_CLOCK'. # The test covers these scenarios: # # 1) With two workers, check if Seconds_Behind_Master is calculated # correctly when two statements are applied in parallel on one database # and both the workers are blocked to to lock. # # 2) With two workers, check if Seconds_Behind_Master is calculated # correctly when the first worker is blocked. # # 3) With three workers, check if Seconds_Behind_Master is calculated # correctly when two workers working on table from the same database and # 3rd worker working on another database. --source include/start_slave.inc ############################################################################### # Scenario 1: On slave, two statements are applied in parallel on one database. # Both workers are blocked. ############################################################################### --echo # Scenario 1: With two workers, check if Seconds_Behind_Master is --echo # calculated correctly when two statements are applied in parallel on --echo # one database and both the workers are blocked to to lock. connect (master2, localhost, root, , ); connection slave; connection master; USE test; CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); # We need one statement to be commited so that the parallel # statements have a common parent commit INSERT INTO t1 SET a=1; --source include/sync_slave_sql_with_master.inc connection slave1; LOCK TABLE test.t1 WRITE, test.t2 WRITE; --connection master1 let $start= `SELECT UNIX_TIMESTAMP()`; BEGIN; INSERT INTO t1 SET a=2; --connection master2 BEGIN; INSERT INTO t2 SET a=4; --connection master1 COMMIT; --connection master2 COMMIT; connection master; --source include/sync_slave_io_with_master.inc # Wait until all workers are blocked by locks. It implies that all # transactions are registered into the order commit queue. let $wait_condition= SELECT count(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for table metadata lock'; --source include/wait_condition.inc let $wait_condition= SELECT count(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Executing event' OR State = 'update'; --source include/wait_condition.inc # Sleep on slave so we were at least 3 seconds behind the master --real_sleep 3 --source include/wait_for_mts_checkpoint.inc let $sbm= query_get_value("SHOW SLAVE STATUS", Seconds_Behind_Master, 1); let $stop= `SELECT UNIX_TIMESTAMP()`; let $upper_bound= `SELECT $stop - $start`; let $assert_text= Seconds_Behind_Master must be between 3 and upper_bound; let $assert_cond= 3 <= $sbm AND $sbm <= $upper_bound; --source include/assert.inc # Unlock tables and allow both workers to complete connection slave1; UNLOCK TABLES; connection master; --source include/sync_slave_sql_with_master.inc let $wait_condition= SELECT count(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for an event from Coordinator'; --source include/wait_condition.inc --source include/wait_for_mts_checkpoint.inc # Now both workers have completed. Thus Seconds_Behind_Master shoud be equal to 0. let $sbm= query_get_value("SHOW SLAVE STATUS", Seconds_Behind_Master, 1); let $assert_text= Seconds_Behind_Master must be 0; let $assert_cond= $sbm = 0; --source include/assert.inc ############################################################################### # Scenario 2: Now only the first worker is blocked. Make sure there is a parent # commit ############################################################################### --echo # Scenario 2: With two workers, check if Seconds_Behind_Master is --echo # calculated correctly when the first worker is blocked. connection master; INSERT INTO t1 SET a=1; --source include/sync_slave_sql_with_master.inc connection slave1; LOCK TABLE test.t1 WRITE; connection slave2; LOCK TABLE test.t2 WRITE; --connection master1 let $start= `SELECT UNIX_TIMESTAMP()`; BEGIN; INSERT INTO t1 SET a=2; --connection master2 BEGIN; INSERT INTO t2 SET a=3; --connection master1 COMMIT; --connection master2 COMMIT; connection master; --source include/sync_slave_io_with_master.inc # Wait until both workers are queued and blocked. let $wait_condition= SELECT count(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for table metadata lock'; --source include/wait_condition.inc let $wait_condition= SELECT count(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Executing event' OR State = 'update'; --source include/wait_condition.inc # Now release one worker connection slave1; UNLOCK TABLES; # Wait until released worker completes its taks let $wait_condition= SELECT count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for table metadata lock'; --source include/wait_condition.inc let $wait_condition= SELECT count(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Executing event' OR State = 'update'; --source include/wait_condition.inc # Sleep for 2 seconds so Seconds_Behind_Master was at least 2 --real_sleep 2 --source include/wait_for_mts_checkpoint.inc let $sbm= query_get_value("SHOW SLAVE STATUS", Seconds_Behind_Master, 1); let $stop= `SELECT UNIX_TIMESTAMP()`; let $upper_bound= `SELECT $stop - $start`; let $assert_text= Seconds_Behind_Master must be between 2 and upper_bound; let $assert_cond= 2 <= $sbm AND $sbm <= $upper_bound; --source include/assert.inc connection slave2; UNLOCK TABLES; --connection master --source include/sync_slave_sql_with_master.inc # All workers should be done by now. let $wait_condition= SELECT count(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for an event from Coordinator'; --source include/wait_condition.inc --source include/wait_for_mts_checkpoint.inc let $sbm= query_get_value("SHOW SLAVE STATUS", Seconds_Behind_Master, 1); let $assert_text= Seconds_Behind_Master must be 0; let $assert_cond= $sbm = 0; --source include/assert.inc ############################################################################### # Scenario 3: Now there are 3 workers working in pararell. Two workers working # on table from the same database and a 3rd worker working on another database ############################################################################### --echo # Scenario 3: With three workers, check if Seconds_Behind_Master is --echo # calculated correctly when two workers working on table from the same --echo # database and 3rd worker working on another database. connection master; CREATE DATABASE second_test; CREATE TABLE second_test.t3 (f1 INT); # Make sure there is a parent commit INSERT INTO test.t1 SET a=1; --sync_slave_with_master # Lock all tables to block all workers. connection slave1; LOCK TABLE test.t1 WRITE; connection slave2; LOCK TABLE test.t2 WRITE; connection slave3; LOCK TABLE second_test.t3 WRITE; connect (master_second_test, localhost, root, , ); --connection master_second_test BEGIN; INSERT INTO second_test.t3 VALUES (1); --connection master1 let $start= `SELECT UNIX_TIMESTAMP()`; BEGIN; INSERT INTO test.t1 SET a=2; --connection master2 BEGIN; INSERT INTO test.t2 SET a=3; --connection master_second_test COMMIT; --connection master1 COMMIT; --connection master2 COMMIT; --source include/sync_slave_io_with_master.inc # Wait for all workers to be queued # There should be two workers waiting for locks on test database let $wait_condition= SELECT count(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for table metadata lock' AND Info LIKE 'INSERT INTO test%'; --source include/wait_condition.inc # And one worker waiting for the lock on second_database let $wait_condition= SELECT count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for table metadata lock' AND Info LIKE 'INSERT INTO second_test%'; --source include/wait_condition.inc # Make sure that there are 3 overall at the same point in time let $wait_condition= SELECT count(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for table metadata lock'; --source include/wait_condition.inc let $wait_condition= SELECT count(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Executing event' OR State = 'update'; --source include/wait_condition.inc # Wait for 2 seconds so Second_Behind_Master is at least 2 --real_sleep 2 --source include/wait_for_mts_checkpoint.inc let $sbm= query_get_value("SHOW SLAVE STATUS", Seconds_Behind_Master, 1); let $stop= `SELECT UNIX_TIMESTAMP()`; let $upper_bound= `SELECT $stop - $start`; let $assert_text= Seconds_Behind_Master must be between 2 and upper_bound; let $assert_cond= 2 <= $sbm AND $sbm <= $upper_bound; --source include/assert.inc # Lets finish concurrent write on second_test and check if workers on test report # correct Seconds_Behind_Master connection slave3; UNLOCK TABLES; --real_sleep 1 connection slave; # Wait till worker on second_test db finishes let $wait_condition= SELECT count(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for table metadata lock' AND Info LIKE 'INSERT INTO second_test%'; --source include/wait_condition.inc # There should be the remaining two workers hanging on test db let $wait_condition= SELECT count(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for table metadata lock' AND Info LIKE 'INSERT INTO test%'; --source include/wait_condition.inc let $wait_condition= SELECT count(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Executing event' OR State = 'update'; --source include/wait_condition.inc --source include/wait_for_mts_checkpoint.inc let $sbm= query_get_value("SHOW SLAVE STATUS", Seconds_Behind_Master, 1); let $stop= `SELECT UNIX_TIMESTAMP()`; let $upper_bound= `SELECT $stop - $start`; let $assert_text= Seconds_Behind_Master must be between 3 and upper_bound; let $assert_cond= 3 <= $sbm AND $sbm <= $upper_bound; --source include/assert.inc # Lets finish worker writing to t1 connection slave1; UNLOCK TABLES; # There should be only one worker left let $wait_condition= SELECT count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for table metadata lock'; --source include/wait_condition.inc let $wait_condition= SELECT count(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Executing event' OR State = 'update'; --source include/wait_condition.inc --real_sleep 1 --source include/wait_for_mts_checkpoint.inc let $sbm= query_get_value("SHOW SLAVE STATUS", Seconds_Behind_Master, 1); let $stop= `SELECT UNIX_TIMESTAMP()`; let $upper_bound= `SELECT $stop - $start`; let $assert_text= Seconds_Behind_Master must be between 4 and upper_bound; let $assert_cond= 4 <= $sbm AND $sbm <= $upper_bound; --source include/assert.inc # Release last worker connection slave2; UNLOCK TABLE; # Wait for all workers to be done let $wait_condition= SELECT count(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for an event from Coordinator'; --source include/wait_condition.inc # All catched up Seconds_Behind_Master should be 0. Lets wait some more to see if it does not increase # Seconds_Behind_Master --real_sleep 1 --source include/wait_for_mts_checkpoint.inc let $sbm= query_get_value("SHOW SLAVE STATUS", Seconds_Behind_Master, 1); let $assert_text= Seconds_Behind_Master must be 0; let $assert_cond= $sbm = 0; --source include/assert.inc # # Cleanup # connection master; DROP TABLE test.t1; DROP TABLE test.t2; DROP DATABASE second_test; --source include/sync_slave_sql_with_master.inc --source include/stop_slave.inc