Replication進階(八) 半同步複製狀態切換
阿新 • • 發佈:2018-11-21
文章目錄
半同步複製狀態切換
一、簡介
假設當前m-s處於半同步複製狀態,這個狀態在某些情況下可能會發生切換。
通過status而不是variables去檢視當前複製狀態
mysql> show global status like 'Rpl_semi_sync_master_status'; +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------+ | Rpl_semi_sync_master_status | ON | +-----------------------------+-------+ 1 row in set (0.00 sec)
如果是ON則為半同步狀態,如果是OFF,則是非同步複製狀態。
二、狀態切換
狀態切換可能是半同步切換到非同步,非同步切換到半同步兩種。
半同步切換非同步狀態
如簡介中所述,如果當前執行在半同步複製狀態,在如下情況下會發生切換
- 等待ack超時,被動切換
事務提交階段需要等待slave返回的ack資訊,並且通過rpl_semi_sync_master_wait_for_slave_count 設定ack slave的數量,通過rpl_semi_sync_master_timeout控制ack超時時間,當master無法在rpl_semi_sync_master_timeout時間內讀取到ack資訊時,則會觸發半同步切換到非同步的過程。這部分的程式碼見如下
if (wait_result != 0) { /* This is a real wait timeout. */ sql_print_warning("Timeout waiting for reply of binlog (file: %s, pos: %lu), " "semi-sync up to file %s, position %lu.", trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos, reply_file_name_, (unsigned long)reply_file_pos_); rpl_semi_sync_master_wait_timeouts++; /* switch semi-sync off */ switch_off(); }
int ReplSemiSyncMaster::switch_off()
{
const char *kWho = "ReplSemiSyncMaster::switch_off";
function_enter(kWho);
state_ = false;
rpl_semi_sync_master_off_times++;
wait_file_name_inited_ = false;
reply_file_name_inited_ = false;
sql_print_information("Semi-sync replication switched OFF.");
/* signal waiting sessions */
active_tranxs_->signal_waiting_sessions_all();
return function_exit(kWho, 0);
}
- 通過設定引數,主動切換
通過設定變數rpl_semi_sync_master_enabled可以手動控制狀態切換
在簡介中,假設當前M-S執行在半同步複製狀態,可以通過如下設定進行切換
mysql> set global rpl_semi_sync_master_enabled=off;
Query OK, 0 rows affected (0.02 sec)
程式碼控制在
引數設定的介面
static MYSQL_SYSVAR_BOOL(enabled, rpl_semi_sync_master_enabled,
PLUGIN_VAR_OPCMDARG,
"Enable semi-synchronous replication master (disabled by default). ",
NULL, // check
&fix_rpl_semi_sync_master_enabled, // update
0);
修改半同步複製狀態
static void fix_rpl_semi_sync_master_enabled(MYSQL_THD thd,
SYS_VAR *var,
void *ptr,
const void *val)
{
*(char *)ptr= *(char *)val;
if (rpl_semi_sync_master_enabled)
{
if (repl_semisync.enableMaster() != 0)
rpl_semi_sync_master_enabled = false;
else if (ack_receiver.start())
{
repl_semisync.disableMaster();
rpl_semi_sync_master_enabled = false;
}
}
else
{
if (repl_semisync.disableMaster() != 0)
rpl_semi_sync_master_enabled = true;
ack_receiver.stop();
}
return;
}
從on->off
int ReplSemiSyncMaster::disableMaster()
{
/* Must have the lock when we do enable of disable. */
lock();
if (getMasterEnabled())
{
/* Switch off the semi-sync first so that waiting transaction will be
* waken up.
*/
switch_off();
if ( active_tranxs_ && active_tranxs_->is_empty())
{
delete active_tranxs_;
active_tranxs_ = NULL;
}
reply_file_name_inited_ = false;
wait_file_name_inited_ = false;
commit_file_name_inited_ = false;
ack_container_.clear();
set_master_enabled(false);
sql_print_information("Semi-sync replication disabled on the master.");
}
unlock();
return 0;
}
非同步切換到半同步
如果初始狀態為半同步,由於其他原因,被迫切換到非同步複製,那麼在某些條件下,可以自動從非同步狀態切換到半同步狀態。
- master-slave網路恢復,master可以正常的接受ack資訊。
void ReplSemiSyncMaster::reportReplyBinlog(const char *log_file_name,
my_off_t log_file_pos)
{
const char *kWho = "ReplSemiSyncMaster::reportReplyBinlog";
int cmp;
bool can_release_threads = false;
bool need_copy_send_pos = true;
function_enter(kWho);
mysql_mutex_assert_owner(&LOCK_binlog_);
if (!getMasterEnabled())
goto l_end;
if (!is_on())
/* We check to see whether we can switch semi-sync ON. */
try_switch_on(log_file_name, log_file_pos);
從程式碼中可以看出,如果引數rpl_semi_sync_master_enabled設定為on,並且當前狀態不為on,則會嘗試進行切換到半同步。
- 如果m-s一開始就執行在非同步環境,則可以通過引數設定切換到半同步狀態
mysql> set global rpl_semi_sync_master_enabled=on;
Query OK, 0 rows affected (0.01 sec)
這個就沒什麼好說的了,常規操作。