Commit b92ec529 authored by He Zhenxing's avatar He Zhenxing

Backport BUG#47298 Semisync: always wait until timeout if no semi-sync slave available

Add an option to control whether the master should keep waiting
until timeout when it detected that there is no semi-sync slave
available.

The bool option 'rpl_semi_sync_master_wait_no_slave' is 1 by
defalt, and will keep waiting until timeout. When set to 0, the
master will switch to asynchronous replication immediately when
no semi-sync slave is available.
parent 64fc766c
...@@ -29,13 +29,13 @@ set global rpl_semi_sync_master_enabled = 1; ...@@ -29,13 +29,13 @@ set global rpl_semi_sync_master_enabled = 1;
show variables like 'rpl_semi_sync_master_enabled'; show variables like 'rpl_semi_sync_master_enabled';
Variable_name Value Variable_name Value
rpl_semi_sync_master_enabled ON rpl_semi_sync_master_enabled ON
[ status of semi-sync on master should be OFF without any semi-sync slaves ] [ 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_clients';
Variable_name Value Variable_name Value
Rpl_semi_sync_master_clients 0 Rpl_semi_sync_master_clients 0
show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_status';
Variable_name Value Variable_name Value
Rpl_semi_sync_master_status OFF Rpl_semi_sync_master_status ON
show status like 'Rpl_semi_sync_master_yes_tx'; show status like 'Rpl_semi_sync_master_yes_tx';
Variable_name Value Variable_name Value
Rpl_semi_sync_master_yes_tx 0 Rpl_semi_sync_master_yes_tx 0
...@@ -210,7 +210,7 @@ include/stop_slave.inc ...@@ -210,7 +210,7 @@ include/stop_slave.inc
[ Semi-sync master status variables before FLUSH STATUS ] [ Semi-sync master status variables before FLUSH STATUS ]
SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx'; SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx';
Variable_name Value Variable_name Value
Rpl_semi_sync_master_no_tx 3 Rpl_semi_sync_master_no_tx 302
SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx'; SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx';
Variable_name Value Variable_name Value
Rpl_semi_sync_master_yes_tx 302 Rpl_semi_sync_master_yes_tx 302
...@@ -355,7 +355,7 @@ Variable_name Value ...@@ -355,7 +355,7 @@ Variable_name Value
Rpl_semi_sync_master_clients 0 Rpl_semi_sync_master_clients 0
show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_status';
Variable_name Value Variable_name Value
Rpl_semi_sync_master_status OFF Rpl_semi_sync_master_status ON
set global rpl_semi_sync_master_enabled= 0; set global rpl_semi_sync_master_enabled= 0;
[ on slave ] [ on slave ]
SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled'; SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled';
...@@ -364,17 +364,17 @@ rpl_semi_sync_slave_enabled ON ...@@ -364,17 +364,17 @@ rpl_semi_sync_slave_enabled ON
include/start_slave.inc include/start_slave.inc
[ on master ] [ on master ]
insert into t1 values (8); insert into t1 values (8);
[ master semi-sync clients should be 0, status should be OFF ] [ 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_clients';
Variable_name Value Variable_name Value
Rpl_semi_sync_master_clients 0 Rpl_semi_sync_master_clients 1
show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_status';
Variable_name Value Variable_name Value
Rpl_semi_sync_master_status OFF Rpl_semi_sync_master_status OFF
[ on slave ] [ on slave ]
show status like 'Rpl_semi_sync_slave_status'; show status like 'Rpl_semi_sync_slave_status';
Variable_name Value Variable_name Value
Rpl_semi_sync_slave_status OFF Rpl_semi_sync_slave_status ON
include/stop_slave.inc include/stop_slave.inc
[ on master ] [ on master ]
set sql_log_bin=0; set sql_log_bin=0;
......
...@@ -74,7 +74,7 @@ echo [ enable semi-sync on master ]; ...@@ -74,7 +74,7 @@ echo [ enable semi-sync on master ];
set global rpl_semi_sync_master_enabled = 1; set global rpl_semi_sync_master_enabled = 1;
show variables like 'rpl_semi_sync_master_enabled'; show variables like 'rpl_semi_sync_master_enabled';
echo [ status of semi-sync on master should be OFF without any semi-sync slaves ]; 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_clients';
show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_status';
show status like 'Rpl_semi_sync_master_yes_tx'; show status like 'Rpl_semi_sync_master_yes_tx';
...@@ -497,7 +497,10 @@ source include/start_slave.inc; ...@@ -497,7 +497,10 @@ source include/start_slave.inc;
connection master; connection master;
echo [ on master ]; echo [ on master ];
insert into t1 values (8); insert into t1 values (8);
echo [ master semi-sync clients should be 0, status should be OFF ]; 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_clients';
show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_status';
sync_slave_with_master; sync_slave_with_master;
......
...@@ -40,6 +40,7 @@ unsigned long long rpl_semi_sync_master_net_wait_num = 0; ...@@ -40,6 +40,7 @@ unsigned long long rpl_semi_sync_master_net_wait_num = 0;
unsigned long rpl_semi_sync_master_clients = 0; unsigned long rpl_semi_sync_master_clients = 0;
unsigned long long rpl_semi_sync_master_net_wait_time = 0; unsigned long long rpl_semi_sync_master_net_wait_time = 0;
unsigned long long rpl_semi_sync_master_trx_wait_time = 0; unsigned long long rpl_semi_sync_master_trx_wait_time = 0;
char rpl_semi_sync_master_wait_no_slave = 1;
static int getWaitTime(const struct timeval& start_tv); static int getWaitTime(const struct timeval& start_tv);
...@@ -525,6 +526,14 @@ void ReplSemiSyncMaster::remove_slave() ...@@ -525,6 +526,14 @@ void ReplSemiSyncMaster::remove_slave()
{ {
lock(); lock();
rpl_semi_sync_master_clients--; rpl_semi_sync_master_clients--;
/* If user has chosen not to wait if no semi-sync slave available
and the last semi-sync slave exits, turn off semi-sync on master
immediately.
*/
if (!rpl_semi_sync_master_wait_no_slave &&
rpl_semi_sync_master_clients == 0)
switch_off();
unlock(); unlock();
} }
...@@ -812,7 +821,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -812,7 +821,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
trx_wait_binlog_pos)); trx_wait_binlog_pos));
/* Update the status counter. */ /* Update the status counter. */
if (is_on() && rpl_semi_sync_master_clients) if (is_on())
rpl_semi_sync_master_yes_transactions++; rpl_semi_sync_master_yes_transactions++;
else else
rpl_semi_sync_master_no_transactions++; rpl_semi_sync_master_no_transactions++;
...@@ -1078,7 +1087,7 @@ int ReplSemiSyncMaster::writeTranxInBinlog(const char* log_file_name, ...@@ -1078,7 +1087,7 @@ int ReplSemiSyncMaster::writeTranxInBinlog(const char* log_file_name,
commit_file_name_inited_ = true; commit_file_name_inited_ = true;
} }
if (is_on() && rpl_semi_sync_master_clients) if (is_on())
{ {
assert(active_tranxs_ != NULL); assert(active_tranxs_ != NULL);
if(active_tranxs_->insert_tranx_node(log_file_name, log_file_pos)) if(active_tranxs_->insert_tranx_node(log_file_name, log_file_pos))
...@@ -1153,7 +1162,7 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id, ...@@ -1153,7 +1162,7 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id,
{ {
sql_print_error("Semi-sync master wait for reply " sql_print_error("Semi-sync master wait for reply "
"gettimeofday fail to get start time"); "gettimeofday fail to get start time");
timefunc_fails_++; rpl_semi_sync_master_timefunc_fails++;
} }
else else
{ {
...@@ -1164,12 +1173,12 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id, ...@@ -1164,12 +1173,12 @@ int ReplSemiSyncMaster::readSlaveReply(NET *net, uint32 server_id,
{ {
sql_print_error("Semi-sync master wait for reply " sql_print_error("Semi-sync master wait for reply "
"gettimeofday fail to get wait time."); "gettimeofday fail to get wait time.");
timefunc_fails_++; rpl_semi_sync_master_timefunc_fails++;
} }
else else
{ {
total_net_wait_num_++; rpl_semi_sync_master_net_wait_num++;
total_net_wait_time_ += wait_time; rpl_semi_sync_master_net_wait_time += wait_time;
} }
} }
} }
...@@ -1242,7 +1251,7 @@ void ReplSemiSyncMaster::setExportStats() ...@@ -1242,7 +1251,7 @@ void ReplSemiSyncMaster::setExportStats()
{ {
lock(); lock();
rpl_semi_sync_master_status = state_ && rpl_semi_sync_master_clients; rpl_semi_sync_master_status = state_;
rpl_semi_sync_master_avg_trx_wait_time= rpl_semi_sync_master_avg_trx_wait_time=
((rpl_semi_sync_master_trx_wait_num) ? ((rpl_semi_sync_master_trx_wait_num) ?
(unsigned long)((double)rpl_semi_sync_master_trx_wait_time / (unsigned long)((double)rpl_semi_sync_master_trx_wait_time /
......
...@@ -363,4 +363,12 @@ extern unsigned long long rpl_semi_sync_master_trx_wait_num; ...@@ -363,4 +363,12 @@ extern unsigned long long rpl_semi_sync_master_trx_wait_num;
extern unsigned long long rpl_semi_sync_master_net_wait_time; extern unsigned long long rpl_semi_sync_master_net_wait_time;
extern unsigned long long rpl_semi_sync_master_trx_wait_time; extern unsigned long long rpl_semi_sync_master_trx_wait_time;
/*
This indicates whether we should keep waiting if no semi-sync slave
is available.
0 : stop waiting if detected no avaialable semi-sync slave.
1 (default) : keep waiting until timeout even no available semi-sync slave.
*/
extern char rpl_semi_sync_master_wait_no_slave;
#endif /* SEMISYNC_MASTER_H */ #endif /* SEMISYNC_MASTER_H */
...@@ -176,6 +176,13 @@ static MYSQL_SYSVAR_ULONG(timeout, rpl_semi_sync_master_timeout, ...@@ -176,6 +176,13 @@ static MYSQL_SYSVAR_ULONG(timeout, rpl_semi_sync_master_timeout,
fix_rpl_semi_sync_master_timeout, // update fix_rpl_semi_sync_master_timeout, // update
10000, 0, ~0L, 1); 10000, 0, ~0L, 1);
static MYSQL_SYSVAR_BOOL(wait_no_slave, rpl_semi_sync_master_wait_no_slave,
PLUGIN_VAR_OPCMDARG,
"Wait until timeout when no semi-synchronous replication slave available (enabled by default). ",
NULL, // check
NULL, // update
1);
static MYSQL_SYSVAR_ULONG(trace_level, rpl_semi_sync_master_trace_level, static MYSQL_SYSVAR_ULONG(trace_level, rpl_semi_sync_master_trace_level,
PLUGIN_VAR_OPCMDARG, PLUGIN_VAR_OPCMDARG,
"The tracing level for semi-sync replication.", "The tracing level for semi-sync replication.",
...@@ -186,6 +193,7 @@ static MYSQL_SYSVAR_ULONG(trace_level, rpl_semi_sync_master_trace_level, ...@@ -186,6 +193,7 @@ static MYSQL_SYSVAR_ULONG(trace_level, rpl_semi_sync_master_trace_level,
static SYS_VAR* semi_sync_master_system_vars[]= { static SYS_VAR* semi_sync_master_system_vars[]= {
MYSQL_SYSVAR(enabled), MYSQL_SYSVAR(enabled),
MYSQL_SYSVAR(timeout), MYSQL_SYSVAR(timeout),
MYSQL_SYSVAR(wait_no_slave),
MYSQL_SYSVAR(trace_level), MYSQL_SYSVAR(trace_level),
NULL, NULL,
}; };
......
...@@ -56,10 +56,11 @@ int repl_semi_slave_request_dump(Binlog_relay_IO_param *param, ...@@ -56,10 +56,11 @@ int repl_semi_slave_request_dump(Binlog_relay_IO_param *param,
} }
row= mysql_fetch_row(res); row= mysql_fetch_row(res);
if (!row || strcmp(row[1], "ON")) if (!row)
{ {
/* Master does not support or not configured semi-sync */ /* Master does not support semi-sync */
sql_print_warning("Master server does not support or not configured semi-sync replication, fallback to asynchronous"); sql_print_warning("Master server does not support semi-sync, "
"fallback to asynchronous replication");
rpl_semi_sync_slave_status= 0; rpl_semi_sync_slave_status= 0;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment