1. 程式人生 > >Replication進階(八) 半同步複製狀態切換

Replication進階(八) 半同步複製狀態切換

文章目錄

半同步複製狀態切換

一、簡介

假設當前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)

這個就沒什麼好說的了,常規操作。