summaryrefslogtreecommitdiffstats
path: root/mysql-test/suite/rpl/t/rpl_parallel_sbm.test
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/suite/rpl/t/rpl_parallel_sbm.test')
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_sbm.test218
1 files changed, 218 insertions, 0 deletions
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_sbm.test b/mysql-test/suite/rpl/t/rpl_parallel_sbm.test
new file mode 100644
index 00000000..58c0db15
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_parallel_sbm.test
@@ -0,0 +1,218 @@
+#
+# Ensure that Seconds_Behind_Master works correctly on the parallel replica.
+#
+--source include/master-slave.inc
+--source include/have_log_bin.inc
+--source include/have_debug.inc
+
+--echo #
+--echo # MDEV-29639: Seconds_Behind_Master is incorrect for Delayed, Parallel Replicas
+--echo #
+
+# This test ensures that after a delayed parallel slave has idled, i.e.
+# executed everything in its relay log, the next event group that the SQL
+# thread reads from the relay log will immediately be used in the
+# Seconds_Behind_Master. In particular, it ensures that the calculation for
+# Seconds_Behind_Master is based on the timestamp of the new transaction,
+# rather than the last committed transaction.
+#
+
+--connection slave
+--source include/stop_slave.inc
+--let $save_dbug= `SELECT @@GLOBAL.debug_dbug`
+--let $save_parallel_mode= `SELECT @@GLOBAL.slave_parallel_mode`
+set @@GLOBAL.debug_dbug= "d,negate_clock_diff_with_master";
+set @@GLOBAL.slave_parallel_mode= CONSERVATIVE;
+--let $master_delay= 3
+--eval change master to master_delay=$master_delay, master_use_gtid=Slave_Pos
+--source include/start_slave.inc
+
+--connection master
+--let insert_ctr= 0
+create table t1 (a int);
+create table t2 (a int);
+--source include/sync_slave_sql_with_master.inc
+
+--echo #
+--echo # Pt 1) Ensure SBM is updated immediately upon arrival of the next event
+
+--connection master
+--echo # Sleep 2 to allow a buffer between events for SBM check
+sleep 2;
+
+--let $ts_trx_before_ins= `SELECT UNIX_TIMESTAMP()`
+--eval insert into t1 values ($insert_ctr)
+--inc $insert_ctr
+--source include/save_master_gtid.inc
+
+--connection slave
+
+--echo # Waiting for transaction to arrive on slave and begin SQL Delay..
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting until MASTER_DELAY seconds after master executed event';
+--source include/wait_condition.inc
+
+--echo # Validating SBM is updated on event arrival..
+--let $sbm_trx1_arrive= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+--let $seconds_since_idling= `SELECT UNIX_TIMESTAMP() - $ts_trx_before_ins`
+if (`SELECT $sbm_trx1_arrive > ($seconds_since_idling + 1)`)
+{
+ --echo # SBM was $sbm_trx1_arrive yet shouldn't have been larger than $seconds_since_idling + 1 (for possible negative clock_diff_with_master)
+ --die Seconds_Behind_Master should reset after idling
+}
+--echo # ..done
+
+
+--echo # MDEV-32265. At time of STOP SLAVE, if the SQL Thread is currently
+--echo # delaying a transaction; then when the reciprocal START SLAVE occurs,
+--echo # if the event is still to be delayed, SBM should resume accordingly
+
+--source include/stop_slave.inc
+--source include/start_slave.inc
+
+--connection slave
+--echo # Waiting for replica to resume the delay for the transaction
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting until MASTER_DELAY seconds after master executed event';
+--source include/wait_condition.inc
+
+--echo # Sleeping 1s to increment SBM
+sleep 1;
+
+--echo # Ensuring Seconds_Behind_Master increases after sleeping..
+--let $sbm_trx1_after_1s_sleep= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+if (`SELECT $sbm_trx1_after_1s_sleep <= $sbm_trx1_arrive`)
+{
+ --echo # ..failed
+ --die Seconds_Behind_Master did not increase after sleeping, but should have
+}
+--echo # ..done
+
+--source include/sync_with_master_gtid.inc
+
+--echo #
+--echo # Pt 2) If the worker threads have not entered an idle state, ensure
+--echo # following events do not update SBM
+
+--connection slave
+LOCK TABLES t1 WRITE;
+
+--connection master
+--echo # Sleep 2 to allow a buffer between events for SBM check
+sleep 2;
+--let $ts_trxpt2_before_ins= `SELECT UNIX_TIMESTAMP()`
+--eval insert into t1 values ($insert_ctr)
+--inc $insert_ctr
+--echo # Sleep 3 to create gap between events
+sleep 3;
+--eval insert into t1 values ($insert_ctr)
+--inc $insert_ctr
+--let $ts_trx_after_ins= `SELECT UNIX_TIMESTAMP()`
+--source include/save_master_pos.inc
+
+--connection slave
+--echo # Wait for first transaction to complete SQL delay and begin execution..
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting for table metadata lock%' AND command LIKE 'Slave_Worker';
+--source include/wait_condition.inc
+
+--echo # Validate SBM calculation doesn't use the second transaction because worker threads shouldn't have gone idle..
+--let $sbm_after_trx_no_idle= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+--let $timestamp_trxpt2_arrive= `SELECT UNIX_TIMESTAMP()`
+if (`SELECT $sbm_after_trx_no_idle < $timestamp_trxpt2_arrive - $ts_trx_after_ins - 1`)
+{
+ --let $cmpv= `SELECT $timestamp_trxpt2_arrive - $ts_trx_after_ins`
+ --echo # SBM $sbm_after_trx_no_idle was more recent than time since last transaction ($cmpv seconds)
+ --die Seconds_Behind_Master should not have used second transaction timestamp
+}
+--let $seconds_since_idling= `SELECT ($timestamp_trxpt2_arrive - $ts_trxpt2_before_ins)`
+--echo # ..and that SBM wasn't calculated using prior committed transactions
+if (`SELECT $sbm_after_trx_no_idle > ($seconds_since_idling + 1)`)
+{
+ --echo # SBM was $sbm_after_trx_no_idle yet shouldn't have been larger than $seconds_since_idling + 1 (for possible negative clock_diff_with_master)
+ --die Seconds_Behind_Master calculation should not have used prior committed transaction
+}
+--echo # ..done
+
+--connection slave
+UNLOCK TABLES;
+--source include/sync_with_master.inc
+
+--echo # Cleanup
+--source include/stop_slave.inc
+--eval CHANGE MASTER TO master_delay=0
+--source include/start_slave.inc
+
+
+--echo #
+--echo # MDEV-30619: Parallel Slave SQL Thread Can Update Seconds_Behind_Master with Active Workers
+--echo #
+
+# This test ensures that a parallel slave will not update
+# Seconds_Behind_Master after the SQL Thread has idled if the worker threads
+# are still executing events. To test this, two events are executed on the
+# primary with $sleep seconds in-between them. Once the second event begins
+# execution on the replica, Seconds_Behind_Master is queried to ensure it
+# reflects the value of the first transaction, rather than the second.
+
+--connection slave
+--echo # Ensure the replica is fully idle before starting transactions
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Slave has read all relay log%';
+--source include/wait_condition.inc
+--let $wait_condition= SELECT count(*)=2 FROM information_schema.processlist WHERE state LIKE 'Waiting for work from SQL thread';
+--source include/wait_condition.inc
+
+--echo # Lock t1 on slave so the first received transaction does not complete/commit
+LOCK TABLES t1 WRITE;
+
+--connection master
+--let $ts_t1_before_master_ins= `SELECT UNIX_TIMESTAMP()`
+--eval insert into t1 values ($insert_ctr)
+--inc $insert_ctr
+--source include/save_master_gtid.inc
+
+--connection slave
+--echo # Waiting for first transaction to begin..
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting for table metadata lock';
+--source include/wait_condition.inc
+
+--let $sbm_1= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+
+--connection master
+--let $sleep = 2
+--echo # Sleep $sleep sec to create a gap between events
+sleep $sleep;
+INSERT INTO t2 VALUES (1);
+--source include/save_master_gtid.inc
+
+--connection slave
+--echo # Waiting for second transaction to begin..
+--let $wait_condition= SELECT count(*) FROM information_schema.processlist WHERE state LIKE 'Waiting for prior transaction to start commit%';
+--source include/wait_condition.inc
+
+--let $sbm_2= query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1)
+
+if (`SELECT $sbm_1 + $sleep > $sbm_2`)
+{
+ --echo # Seconds_Behind_Masters: $sbm_1 $sbm_2_0
+ --die Two successive Seconds_Behind_Master timestamps must be separated by the sleep parameter value or greater
+}
+
+--connection slave
+UNLOCK TABLES;
+--source include/sync_with_master_gtid.inc
+
+
+--echo #
+--echo # Cleanup
+
+--connection master
+DROP TABLE t1, t2;
+--source include/save_master_gtid.inc
+
+--connection slave
+--source include/sync_with_master_gtid.inc
+--source include/stop_slave.inc
+--eval set @@GLOBAL.debug_dbug= "$save_dbug"
+--evalp set @@GLOBAL.slave_parallel_mode= "$save_parallel_mode"
+--source include/start_slave.inc
+
+--source include/rpl_end.inc
+--echo # End of rpl_parallel_sbm.test