1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00
Files
mariadb/mysql-test/suite/rpl/t/rpl_heartbeat.test
Kristian Nielsen 84da20e658 MDEV-34705: Binlog-in-engine: Protect against concurrent RESET MASTER and dump threads
This is actually an existing problem in the old binlog implementation, and
this patch is applicable to old binlog also. The problem is that RESET
MASTER can run concurrently with binlog dump threads / connected slaves.
This will remove the binlog from under the feet of the reader, which can
cause all sorts of strange behaviour.

This patch fixes the problem by disallowing to run RESET MASTER when dump
threads (or other RESET MASTER or SHOW BINARY LOGS) are running. An error is
thrown in this case, user must stop slaves and/or kill dump threads to make
the RESET MASTER go through. A slave that connects in the middle of RESET
MASTER will wait for it to complete.

Fix a lot of test cases to kill any lingering dump threads before doing
RESET MASTER, mostly just by sourcing include/kill_binlog_dump_threads.inc.

Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
2025-07-23 16:19:50 +02:00

177 lines
5.6 KiB
Plaintext

# Testing master to slave heartbeat protocol
#
# Including:
# - user interface, grammar, checking the range and warnings about
# unreasonable values for the heartbeat period;
# - no rotation of relay log if heartbeat is less that slave_net_timeout
# - SHOW STATUS like 'Slave_received_heartbeats' action
# - SHOW STATUS like 'Slave_heartbeat_period' report
-- source include/have_log_bin.inc
-- source include/master-slave.inc
connection slave;
-- source include/stop_slave.inc
connection master;
--source include/kill_binlog_dump_threads.inc
reset master;
connection slave;
set @restore_slave_net_timeout= @@global.slave_net_timeout;
--disable_warnings
set @@global.slave_net_timeout= 10;
--enable_warnings
--enable_prepare_warnings
###
### Checking the range
###
#
# default period slave_net_timeout/2
#
--replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
--query_vertical show status like 'Slave_heartbeat_period';
#
# the max for the period is ULONG_MAX/1000; an attempt to exceed it is denied
#
--replace_result $MASTER_MYPORT MASTER_PORT
--error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4294968;
--query_vertical show status like 'Slave_heartbeat_period';
#
# the min value for the period is 1 millisecond an attempt to assign a
# lesser will be warned with treating the value as zero
#
connection slave;
--replace_result $MASTER_MYPORT MASTER_PORT
### 5.1 mtr does not have --warning ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 0.0009999;
--query_vertical show status like 'Slave_heartbeat_period';
#
# the actual max and min must be accepted
#
--replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4294967;
--query_vertical show status like 'Slave_heartbeat_period';
--replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 0.001;
--query_vertical show status like 'Slave_heartbeat_period';
reset slave;
#
# A warning if period greater than slave_net_timeout
#
set @@global.slave_net_timeout= 5;
--replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 5.001;
--query_vertical show status like 'Slave_heartbeat_period';
reset slave;
#
# A warning if slave_net_timeout is set to less than the current HB period
#
set @@global.slave_net_timeout= 5;
--replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4;
--query_vertical show status like 'Slave_heartbeat_period';
set @@global.slave_net_timeout= 3 /* must be a warning */;
reset slave;
###
### checking no rotation
###
connection master;
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Even though master_heartbeat_period= 0.5 is 20 times less than
# @@global.slave_net_timeout= 10 in some circumstances master will
# not be able to send any heartbeat during the slave's net timeout
# and slave's relay log will rotate.
# The probability for such a scenario is pretty small so the following
# part is almost deterministic.
#
connection slave;
set @@global.slave_net_timeout= 10;
--replace_result $MASTER_MYPORT MASTER_PORT
# no error this time but rather a warning
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_ssl_verify_server_cert=0, master_heartbeat_period= 0.5;
--query_vertical show status like 'Slave_heartbeat_period';
start slave;
connection master;
create table t1 (f1 int);
#connection slave;
sync_slave_with_master;
let $slave_param= Relay_Log_File;
let $slave_param_value= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1);
# there is an explicit sleep lasting longer than slave_net_timeout
# to ensure that nothing will come to slave from master for that period.
# That would cause reconnecting and relaylog rotation w/o the fix i.e
# without a heartbeat received.
real_sleep 15;
# check (compare with the previous show's results) that no rotation happened
source include/check_slave_param.inc;
###
### SHOW STATUS like 'Slave_heartbeat_period' and 'Slave_received_heartbeats'
###
--query_vertical show status like 'Slave_heartbeat_period';
#
# proof that there has been received at least one heartbeat;
# The exact number of received heartbeat is an indeterministic value
# and therefore it's not recorded into results.
#
let $slave_wait_param_counter= 300;
let $slave_value= query_get_value("SHOW STATUS like 'Slave_received_heartbeats'", Value, 1);
# Checking the fact that at least one heartbeat is received
while (!$slave_value)
{
dec $slave_wait_param_counter;
if (!$slave_wait_param_counter)
{
--echo ERROR: failed while waiting for slave parameter $slave_param: $slave_param_value
query_vertical show slave status;
SHOW STATUS like 'Slave_received_heartbeats';
exit;
}
sleep 0.1;
let $slave_value= query_get_value("SHOW STATUS like 'Slave_received_heartbeats'", Value, 1);
}
--echo A heartbeat has been received by the slave
# cleanup
connection master;
drop table t1;
#connection slave;
sync_slave_with_master;
set @@global.slave_net_timeout= @restore_slave_net_timeout;
--disable_prepare_warnings
--source include/rpl_end.inc
--echo End of tests