MySQL Shell 9.0  /  MySQL InnoDB ClusterSet  /  InnoDB ClusterSet 緊急故障轉移

8.8 InnoDB ClusterSet 緊急故障轉移

緊急故障轉移會將選定的複本叢集設為 InnoDB ClusterSet 部署的主要 InnoDB 叢集。當目前的主要叢集無法運作或無法連線時,可以使用此程序。在緊急故障轉移過程中,無法保證資料一致性,因此為了安全起見,原始主要叢集在故障轉移過程中會被標記為失效。如果原始主要叢集保持連線,則應在可以連線時立即關閉。如果可以修正問題,則可以在之後修復失效的主要叢集並重新加入至 InnoDB ClusterSet 拓樸。

當 InnoDB ClusterSet 部署中的主要 InnoDB 叢集發生問題或無法存取時,請勿立即將緊急故障轉移實作至複本叢集。相反地,您應始終先嘗試修復目前作用中的主要叢集。

重要事項

為什麼不直接故障轉移?InnoDB ClusterSet 拓樸中的複本叢集會盡力與主要叢集保持同步。但是,根據交易量以及主要叢集和複本叢集之間網路連線的速度和容量,複本叢集在接收交易並將變更套用至其資料方面可能會落後於主要叢集。這稱為複寫延遲。在大多數複寫拓樸中,預期會有某些複寫延遲,而且在叢集地理位置分散且位於不同資料中心的 InnoDB ClusterSet 部署中,這種情況非常有可能發生。

此外,主要叢集可能因網路分割而與 InnoDB ClusterSet 拓樸的其他元素斷線,但仍保持連線。如果發生這種情況,某些複本叢集可能會與主要叢集保持連線,而且某些執行個體和用戶端應用程式可能會繼續連線至主要叢集並套用交易。在這種情況下,InnoDB ClusterSet 拓樸的分割區域會開始彼此發散,每個伺服器群組上都有不同的交易集。

當有複寫延遲或網路分割時,如果您觸發緊急故障轉移至複本叢集,則主要叢集上任何未複寫或發散的交易都有遺失的風險。在網路分割的情況下,故障轉移可能會產生腦裂情況,其中拓樸的不同部分具有發散的交易集。因此,在觸發緊急故障轉移之前,您應始終嘗試修復或重新連線主要叢集。如果無法快速修復主要叢集或無法連線,您可以繼續進行緊急故障轉移。

此圖顯示在範例 InnoDB ClusterSet 部署中緊急故障轉移的效果。羅馬資料中心的主要叢集已離線,因此已執行緊急故障轉移,將布魯塞爾資料中心的複本叢集設為 InnoDB ClusterSet 部署的主要 InnoDB 叢集。羅馬叢集已標記為失效,而且其在 InnoDB ClusterSet 部署中的狀態已降級為複本叢集,儘管目前無法從布魯塞爾叢集複寫交易。

圖 8.3 InnoDB ClusterSet 故障轉移

The InnoDB Cluster in the Rome datacenter is now offline and invalidated, and the InnoDB Cluster in the Brussels datacenter is now the primary cluster. Asynchronous replication between the two is not taking place because the Rome cluster is not available. The MySQL Router instances that targeted the primary or the Brussels cluster are sending traffic to the Brussels cluster. The instance that specifically targeted the Rome cluster cannot send traffic to the cluster.

設定為跟隨主要叢集的 MySQL Router 執行個體已將讀取和寫入流量路由至目前為主要叢集的布魯塞爾叢集。當布魯塞爾叢集是複本叢集時,依名稱將讀取流量路由至該叢集的 MySQL Router 執行個體會繼續將流量路由至該叢集,而且不會受到叢集現在是主要叢集而不是複本叢集的事實所影響。但是,依名稱將讀取流量路由至羅馬叢集的 MySQL Router 執行個體目前無法在那裡傳送任何流量。在此範例中,報告應用程式不需要在當地資料中心離線時回報,但如果應用程式仍然需要運作,則應變更 MySQL Router 執行個體的路由選項,以跟隨主要叢集或將流量傳送至布魯塞爾叢集。

若要為主要 InnoDB 叢集執行緊急故障轉移,請遵循此程序

  1. 使用 MySQL Shell,使用 InnoDB 叢集管理員帳戶 (使用 cluster.setupAdminAccount() 建立) 連線至 InnoDB ClusterSet 部署中仍然作用中的任何成員伺服器。您也可以使用 InnoDB 叢集伺服器組態帳戶,該帳戶也具有所需的權限。

    建立連線後,使用 dba.getClusterSet()cluster.getClusterSet() 命令,從該成員伺服器取得 ClusterSet 物件。您先前從現在離線的成員伺服器擷取的 ClusterSet 物件將不再運作,因此您需要再次從連線的伺服器取得。請務必使用 InnoDB 叢集管理員帳戶或伺服器組態帳戶,以便儲存在 ClusterSet 物件中的預設使用者帳戶具有正確的權限。例如

    mysql-js> \connect admin2@127.0.0.1:4410
    Creating a session to 'admin2@127.0.0.1:4410'
    Please provide the password for 'admin2@127.0.0.1:4410': ********
    Save password for 'admin2@127.0.0.1:4410'? [Y]es/[N]o/Ne[v]er (default No):
    Fetching schema names for autocompletion... Press ^C to stop.
    Closing old connection...
    Your MySQL connection id is 71
    Server version: 8.0.27-commercial MySQL Enterprise Server - Commercial
    No default schema selected; type \use <schema> to set one.
    <ClassicSession:admin2@127.0.0.1:4410>
    
    mysql-js> myclusterset = dba.getClusterSet()
    <ClusterSet:testclusterset>
  2. 使用 MySQL Shell 中 AdminAPI 的 clusterSet.status() 函數,檢查整個部署的狀態。使用 extended 選項來查看問題的確切位置和內容。例如

    mysql-js> myclusterset.status({extended: 1})

    如需輸出說明,請參閱第 8.6 節,〈InnoDB ClusterSet 狀態和拓樸〉

  3. InnoDB 叢集可以容忍一些問題,並且運作良好,足以繼續作為 InnoDB ClusterSet 部署的一部分。當您使用 clusterSet.status() 命令檢查時,運作可接受的主要叢集的全域狀態為 OK。例如,如果叢集中的其中一個成員伺服器離線,即使該伺服器是主要的伺服器,基礎群組複寫技術也可以處理這種情況並自行重新設定。

    如果根據回報的狀態,主要叢集在 InnoDB ClusterSet 部署中仍然運作可接受,但您需要執行維護或修正一些小問題來改善主要叢集的功能,則您可以執行受控切換至複本叢集。然後,您可以視需要將主要叢集離線,修復任何問題,並將其重新帶回 InnoDB ClusterSet 部署中運作。如需執行此動作的指示,請參閱第 8.7 節,〈InnoDB ClusterSet 受控切換〉

  4. 如果主要叢集在 InnoDB ClusterSet 部署中運作不可接受 (全域狀態為 NOT_OK),但您可以連線到它,請先嘗試使用透過 MySQL Shell 的 AdminAPI 修復任何問題。例如,如果主要叢集遺失仲裁,可以使用 cluster.forceQuorumUsingPartitionOf 命令來還原。如需執行此動作的指示,請參閱第 8.9 節,〈InnoDB ClusterSet 修復和重新加入〉

  5. 如果您無法執行受控切換,並且無法透過使用主要叢集來快速修正問題 (例如,因為您無法連線到它),請繼續進行緊急故障轉移。首先,識別適合接管為主要叢集的複本叢集。複本叢集是否符合緊急故障轉移的資格取決於其全域狀態,如 clusterSet.status() 命令所回報

    表 8.2 按狀態允許的叢集作業

    ClusterSet 中的 InnoDB 叢集全域狀態 可路由 受控切換 緊急故障轉移
    OK
    OK_NOT_REPLICATING 是,如果依名稱指定為目標叢集
    OK_NOT_CONSISTENT 是,如果依名稱指定為目標叢集
    OK_MISCONFIGURED
    NOT_OK
    INVALIDATED 是,如果依名稱指定為目標叢集,並設定 accept_ro 路由原則
    UNKNOWN 已連線的路由器執行個體可能仍在將流量路由至叢集

    您選取的複本叢集必須在所有可連線的複本叢集中,擁有最新的交易集 (GTID 集)。如果有多個複本叢集符合緊急故障轉移的資格,請檢查每個叢集的複寫延遲 (該延遲會顯示在 clusterSet.status() 命令的擴充輸出中)。選取複寫延遲最小的複本叢集,該叢集應該擁有最多的交易。緊急故障轉移程序會檢查目前可連線的所有複本叢集的 GTID 集,並告訴您是否有另一個叢集比較新,因此您可以使用該叢集再次嘗試。

  6. 藉由在連線至 InnoDB ClusterSet 部署中任何成員伺服器的同時,在 MySQL Shell 中發出 clusterSet.routingOptions() 命令,檢查為每個 MySQL Router 執行個體設定的路由選項,以及 InnoDB ClusterSet 部署的全域原則。例如

    mysql-js> myclusterset.routingOptions()
    {
        "domainName": "testclusterset",
        "global": {
            "invalidated_cluster_policy": "drop_all",
            "target_cluster": "primary"
        },
        "routers": {
            "Rome1":  {
                "target_cluster": "primary"
            },
            "Rome2": {}
        }
    }

    如果所有 MySQL Router 實例都設定為追隨主要叢集("target_cluster": "primary"),則在容錯移轉發生後的幾秒內,流量會自動重新導向至新的主要叢集。如果 MySQL Router 實例的路由選項未顯示,如上述範例中 Rome2"target_cluster",則表示該實例未設定該策略,而是遵循全域策略。

    如果任何實例設定為依名稱鎖定目前的主要叢集("target_cluster": "name_of_primary_cluster"),則它們不會將流量重新導向至新的主要叢集。當主要叢集無法運作時,無法使用 clusterSet.setRoutingOption() 命令來變更路由選項,因此在容錯移轉至新的主要叢集完成之前,您無法重新導向由該 MySQL Router 實例處理的流量。

  7. 如果可以,請嘗試驗證原始的主要叢集是否離線,如果它在線上,請嘗試將其關閉。如果它保持在線上並繼續接收來自用戶端的流量,則可能會產生分割大腦的情況,其中 InnoDB ClusterSet 的分離部分會產生分歧。

  8. 若要繼續緊急容錯移轉,請發出 clusterSet.forcePrimaryCluster() 命令,並指定將接管成為新的主要叢集的複本叢集。例如:

    mysql-js> myclusterset.forcePrimaryCluster("clustertwo")
    Failing-over primary cluster of the clusterset to 'clustertwo'
    * Verifying primary cluster status
    None of the instances of the PRIMARY cluster 'clusterone' could be reached.
    * Verifying clusterset status
    ** Checking cluster clustertwo
      Cluster 'clustertwo' is available
    ** Checking whether target cluster has the most recent GTID set
    * Promoting cluster 'clustertwo'
    * Updating metadata
    
    PRIMARY cluster failed-over to 'clustertwo'. The PRIMARY instance is '127.0.0.1:4410'
    Former PRIMARY cluster was INVALIDATED, transactions that were not yet replicated may be lost.

    clusterSet.forcePrimaryCluster() 命令中:

    • clusterName 參數為必要參數,並指定 InnoDB ClusterSet 中用於複本叢集的識別碼,如 clusterSet.status() 命令的輸出所示。在範例中,clustertwo 是要成為新的主要叢集的叢集。

    • 如果您想要執行驗證並記錄變更,而不實際執行它們,請使用 dryRun 選項。

    • 使用 invalidateReplicaClusters 選項來指定任何無法連線或無法使用的複本叢集。這些叢集在容錯移轉過程中將被標記為失效。如果在過程中發現任何您未指定的無法連線或無法使用的複本叢集,容錯移轉將會取消。在此情況下,您必須修復並重新加入複本叢集,然後重試命令,或在重試命令時指定它們,並稍後再修復它們。

    • 使用 timeout 選項來定義在叢集的每個實例中,等待套用擱置交易的最長時間(以秒為單位)。確保 GTID_EXECUTED 具有最新的 GTID 集。預設值是從 dba.gtidWaitTimeout 選項中擷取。

    當您發出 clusterSet.forcePrimaryCluster() 命令時,MySQL Shell 會檢查目標複本叢集是否符合接管成為主要叢集的要求,如果不符合,則會傳回錯誤。

    如果目標複本叢集符合要求,MySQL Shell 會執行下列工作:

    • 嘗試聯絡目前的主要叢集,如果實際上可以連線到它,則會停止容錯移轉。

    • 檢查是否有任何未使用 invalidateReplicaClusters 指定的無法連線或無法使用的複本叢集,如果找到任何叢集,則會停止容錯移轉。

    • invalidateReplicaClusters 中列出的所有複本叢集標記為失效,並將舊的主要叢集標記為失效。

    • 檢查目標複本叢集是否在可用的複本叢集中具有最新的 GTID 集。這需要停止所有複本叢集中的 ClusterSet 複寫通道。

    • 更新所有複本叢集上的 ClusterSet 複寫通道,以從目標叢集複寫為新的主要叢集。

    • 將目標叢集設定為 ClusterSet 中主要叢集,並將舊的主要叢集變更為複本叢集,但它目前不會作為複本叢集運作,因為它被標記為失效。

    在緊急容錯移轉期間,MySQL Shell 不會嘗試將目標複本叢集與目前的主要叢集同步,也不會鎖定目前的主要叢集。如果原始的主要叢集保持在線上,則應在可以聯絡到它時立即將其關閉。

  9. 如果您有任何 MySQL Router 實例要切換至以新的主要叢集為目標,請立即執行此操作。您可以將它們變更為追隨主要叢集("target_cluster": "primary"),或指定已接管為主要叢集的複本叢集("target_cluster": "name_of_new_primary_cluster")。例如:

    mysql-js> myclusterset.setRoutingOption('Rome1', 'target_cluster', 'primary')
    or
    mysql-js> myclusterset.setRoutingOption('Rome1', 'target_cluster', 'clustertwo')
    Routing option 'target_cluster' successfully updated in router 'Rome1'.

    發出 clusterSet.routingOptions() 命令,以檢查所有 MySQL Router 實例現在是否正確路由。

  10. 再次使用 extended 選項發出 clusterSet.status() 命令,以驗證 InnoDB ClusterSet 部署的狀態。

  11. 如果您能夠再次聯絡到舊的主要叢集,請先確保沒有任何應用程式流量路由到它,然後將其離線。然後,依照第 8.9 節,「InnoDB ClusterSet 修復和重新加入」中的程序,檢查交易並決定如何安排 InnoDB ClusterSet 的未來拓撲。

    在緊急容錯移轉後,由於 ClusterSet 的各部分之間的交易集可能存在差異的風險,您必須將叢集從寫入流量或所有流量中隔離。有關更多詳細資訊,請參閱InnoDB ClusterSet 中的隔離叢集

    如果您在切換過程中必須將任何複本叢集失效,則在您能夠再次聯絡到它們時,可以使用第 8.9 節,「InnoDB ClusterSet 修復和重新加入」中的程序來修復它們並將它們重新新增回 InnoDB ClusterSet。