mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 06:44:16 +01:00
55842061e7
Semi-sync uses an extra connection from slave to master to send replies, this is a normal client connection, and used a normal SET query to set the reply information on master, which is visible to user and may cause some confusion and complaining. This problem is fixed by using the method of sending reply by using the same connection that is used by master dump thread to send binlog to slave. Since now the semi-sync plugins are integrated with the server code, it is not a problem to use the internal net interfaces to do this. The master dump thread will mark the event requires a reply and wait for the reply when the event just sent is the last event of a transaction and semi-sync status is ON; And the slave will send a reply to master when it received such an event that requires a reply.
567 lines
16 KiB
Text
567 lines
16 KiB
Text
source include/have_semisync_plugin.inc;
|
|
source include/not_embedded.inc;
|
|
source include/not_windows.inc;
|
|
source include/have_innodb.inc;
|
|
source include/master-slave.inc;
|
|
|
|
let $engine_type= InnoDB;
|
|
#let $engine_type= MyISAM;
|
|
|
|
# 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);
|
|
|
|
# Suppress warnings that might be generated during the test
|
|
disable_query_log;
|
|
connection master;
|
|
call mtr.add_suppression("Timeout waiting for reply of binlog");
|
|
connection slave;
|
|
call mtr.add_suppression("Master server does not support");
|
|
# These will be removed after fix bug#45852
|
|
call mtr.add_suppression("Set 'rpl_semi_sync_master_reply_log_file_pos' on master failed");
|
|
call mtr.add_suppression("Slave I/O: Fatal error: Failed to run 'after_queue_event' hook, Error_code: 1593");
|
|
enable_query_log;
|
|
|
|
--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;
|
|
INSTALL PLUGIN rpl_semi_sync_master SONAME 'libsemisync_master.so';
|
|
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 OFF 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;
|
|
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'libsemisync_slave.so';
|
|
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 # Test semi-sync master will switch OFF after one transacton
|
|
--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;
|
|
|
|
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);
|
|
echo [ master semi-sync clients should be 0, 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;
|
|
INSTALL PLUGIN rpl_semi_sync_master SONAME 'libsemisync_master.so';
|
|
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 ];
|
|
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'libsemisync_slave.so';
|
|
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;
|