MySQL Shell 8.4  /  MySQL InnoDB ClusterSet  /  InnoDB ClusterSet 控制的切換

8.7 InnoDB ClusterSet 控制的切換

受控制的切換會將選定的複本叢集轉換為 InnoDB ClusterSet 部署的主要叢集。在受控制的切換過程中,可確保資料一致性。此程序會驗證選定的複本叢集是否與主要叢集同步 (如果複製延遲,可能表示需要短暫等待),然後將該叢集轉換為 InnoDB ClusterSet 的主要叢集。原始主要叢集會降級為唯讀複本叢集。然後,您可以視需要將原始主要叢集離線、修復任何問題,並將其重新加入 InnoDB ClusterSet 部署中。

如果 InnoDB ClusterSet 部署中的主要叢集運作狀況尚可接受,但您需要執行維護或修復一些小問題以改善主要叢集的功能,請遵循受控制的切換程序。運作狀況尚可接受的主要叢集在使用 MySQL Shell 中的 AdminAPI 的 clusterSet.status() 命令進行檢查時,其全域狀態為 OK

如果 InnoDB ClusterSet 部署中的主要叢集運作狀況不佳 (全域狀態為 NOT_OK),請先嘗試透過 MySQL Shell 使用 AdminAPI 修復任何問題。例如,如果主要叢集失去仲裁,可以使用 cluster.forceQuorumUsingPartitionOf 命令還原。如需執行此操作的指示,請參閱第 8.9 節「InnoDB ClusterSet 修復和重新加入」

如果您無法透過處理主要叢集來修復問題 (例如,因為您無法連線到它),則需要執行緊急容錯移轉。緊急容錯移轉的設計目的是在主要叢集突然無法使用時進行災害復原。此程序會帶來遺失交易和為 InnoDB ClusterSet 建立腦裂情況的風險。如果您確實需要執行緊急容錯移轉,請遵循第 8.8 節「InnoDB ClusterSet 緊急容錯移轉」中的程序,以確保風險受到管理。

該圖顯示在範例 InnoDB ClusterSet 部署中受控制切換的效果。羅馬資料中心的主要叢集需要維護,因此已執行受控制的切換,以將布魯塞爾資料中心的複本叢集轉換為 InnoDB ClusterSet 部署的主要叢集,並將羅馬叢集降級為複本。羅馬叢集上的 ClusterSet 複製通道已由受控制的切換程序啟用,並且正在從布魯塞爾叢集複製交易。現在羅馬叢集是複本叢集,如果需要執行維護工作,可以安全地將成員伺服器或整個叢集離線。

圖 8.2 InnoDB ClusterSet 切換

The InnoDB Cluster in the Rome datacenter is now a replica cluster, and the InnoDB Cluster in the Brussels datacenter is now the primary cluster. The asynchronous replication channel is now sending transactions from the Brussels cluster to the Rome cluster. 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 can continue to send traffic to it because it is only sending read traffic.

範例 InnoDB 叢集部署中設定為追蹤主要叢集的 MySQL Router 執行個體已將讀取和寫入流量路由至現在是主要叢集的布魯塞爾叢集。當布魯塞爾叢集為複本叢集時,依名稱將讀取流量路由至布魯塞爾叢集的 MySQL Router 執行個體,會繼續將流量路由至該叢集,而且不會受到該叢集現在是主要叢集而非複本叢集的事實影響。同樣地,依名稱將讀取流量路由至羅馬叢集的 MySQL Router 執行個體可以繼續執行此操作,因為複本叢集仍然接受讀取流量。

若要對主要 InnoDB 叢集執行受控制的切換,請遵循此程序

  1. 使用 MySQL Shell,使用 InnoDB 叢集管理員帳戶 (使用 cluster.setupAdminAccount() 建立) 連線到主要叢集或其中一個複本叢集中的任何成員伺服器。您也可以使用 InnoDB 叢集伺服器組態帳戶,該帳戶也具有必要的權限。使用 dba.getClusterSet()cluster.getClusterSet() 命令取得 ClusterSet 物件。務必使用 InnoDB 叢集管理員帳戶或伺服器組態帳戶,以便儲存在 ClusterSet 物件中的預設使用者帳戶具有正確的權限。例如

    mysql-js> \connect admin2@127.0.0.1:3310
    Creating a session to 'admin2@127.0.0.1:3310'
    Please provide the password for 'admin2@127.0.0.1:3310': ********
    Save password for 'admin2@127.0.0.1:3310'? [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 52
    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:3310>
    mysql-js> myclusterset = dba.getClusterSet()
    <ClusterSet:testclusterset>

    在此範例中

    • admin2@127.0.0.1:3310 是叢集中任何上線成員伺服器執行個體的 URI 類似連線字串。

      URI 類似連線字串包含下列元素

    • admin2 是 InnoDB 叢集管理員帳戶的使用者名稱。

    • 127.0.0.1:3310 是成員伺服器執行個體的主機和連接埠,如 cluster.status() 命令所顯示。

    • 傳回的 ClusterSet 物件會指派給變數 myclusterset

  2. 使用 MySQL Shell 中的 AdminAPI 的 clusterSet.status() 命令檢查整個 InnoDB ClusterSet 部署的狀態。使用 extended 選項檢視部署中所有叢集的詳細資訊,並檢查是否有任何問題。例如

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

    如需輸出的說明,請參閱第 8.6 節「InnoDB ClusterSet 狀態和拓撲」

  3. 找出適合接管為主要叢集的複本叢集。複本叢集是否有資格進行受控制的切換取決於其全域狀態,如 clusterSet.status() 命令所報告

    表 8.1 依狀態允許的叢集操作

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

    全域狀態為 OK_NOT_CONSISTENT 的複本叢集在叢集上有一組與主要叢集上的 GTID 集不一致的交易 (GTID 集)。InnoDB ClusterSet 不允許受控制的切換到此狀態的叢集,因為用戶端會存取不正確的資料。如果叢集在可用選項中具有最新的交易集,則可以執行緊急容錯移轉。

  4. 在連線到 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 執行個體會將流量傳送至目前為 InnoDB ClusterSet 部署中主要叢集的叢集。如果所有 MySQL Router 執行個體都設定為追蹤主要叢集 ("target_cluster": "primary"),則會在切換後的幾秒內將流量自動重新導向至新的主要叢集。如果未顯示 MySQL Router 執行個體的路由選項,例如上述範例中的 Rome2,則表示該執行個體沒有設定該原則,並且遵循全域原則。

    如果任何執行個體設定為依名稱鎖定目前的主要叢集 ("target_cluster": "name_of_primary_cluster"),則不會將流量重新導向至新的主要叢集。在該情況下,如果應用程式適用,您可以使用 clusterSet.setRoutingOption() 命令來變更這些執行個體的路由原則。您可以將這些執行個體變更為追蹤主要叢集 ("target_cluster": "primary"),在這種情況下,現在可以設定該選項。例如

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

    在這個範例中,myclustersetClusterSet 物件的變數,而 Rome1 是 MySQL Router 執行個體的名稱。

    或者,您可以指定將接管成為主要叢集的複本叢集,在這種情況下,請在切換完成且您已驗證其運作正常後,設定選項 ("target_cluster": "name_of_new_primary_cluster")。

  5. 發出 clusterSet.setPrimaryCluster() 命令,命名將接管成為新主要叢集的複本叢集。使用您透過 InnoDB Cluster 管理員帳戶,使用 dba.getClusterSet()cluster.getClusterSet() 命令所擷取的 ClusterSet 物件。例如

    mysql-js> myclusterset.setPrimaryCluster('clustertwo')
    Switching the primary cluster of the clusterset to 'clustertwo'
    * Verifying clusterset status
    ** Checking cluster clustertwo
      Cluster 'clustertwo' is available
    ** Checking cluster clusterone
      Cluster 'clusterone' is available
    
    * Refreshing replication account of demoted cluster
    * Synchronizing transaction backlog at 127.0.0.1:4410
    ** Transactions replicated  ############################################################  100%
    * Updating metadata
    
    * Updating topology
    ** Changing replication source of 127.0.0.1:3330 to 127.0.0.1:4410
    * Acquiring locks in replicaset instances
    ** Pre-synchronizing SECONDARIES
    ** Acquiring global lock at PRIMARY
    ** Acquiring global lock at SECONDARIES
    
    * Synchronizing remaining transactions at promoted primary
    ** Transactions replicated  ############################################################  100%
    * Updating replica clusters
    Cluster 'clustertwo' was promoted to PRIMARY of the clusterset. The PRIMARY instance is '127.0.0.1:4410'

    針對 clusterSet.setPrimaryCluster() 命令

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

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

    • 使用 timeout 選項設定複本叢集與主要叢集同步的最大等待秒數,然後才會進行切換。如果逾時到期,則會取消切換。

    • 使用 invalidateReplicaClusters 選項來命名任何無法連線或無法使用的複本叢集。這些會在切換過程中被標示為失效。如果在過程中發現任何您未命名的無法連線或無法使用的複本叢集,則會取消切換。在這種情況下,您必須修復並重新加入複本叢集,然後重試命令,或在重試命令時在此選項上命名它們,然後稍後修復它們。

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

    • 檢查是否有任何未使用 invalidateReplicaClusters 指定的無法連線或無法使用的複本叢集。

    • 等待目標複本叢集透過套用來自主要叢集的任何未完成交易,與目前的主要叢集同步。如果 timeout 選項設定的逾時在複本叢集完成套用交易之前到期,則會取消切換。

    • 透過發出 FLUSH TABLES WITH READ LOCK 陳述式,並在所有成員伺服器上設定 super_read_only 系統變數,來鎖定目前的主要叢集,以防止切換期間的進一步變更。群組複寫成員動作 mysql_disable_super_read_only_if_primary 會停用,以便在容錯移轉後 super_read_only 保持設定。

    • 協調目前主要叢集和複本叢集之間檢視變更事件的差異,以便 GTID 集相同。這些群組複寫內部交易由 group_replication_view_change_uuid 系統變數指定的 UUID 識別。MySQL Shell 會在所有複本叢集上注入空交易,以符合主要叢集上的檢視變更事件。

      注意

      執行 MySQL Server 8.3.0 或更高版本的叢集不需要此操作。

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

    • 在目標叢集的主要伺服器上停用 super_read_only,並啟用群組複寫成員動作 mysql_disable_super_read_only_if_primary,以處理該叢集中主要伺服器的任何變更。

    • 在舊主要叢集的主要伺服器上停用群組複寫成員動作 mysql_disable_super_read_only_if_primary,以便它保持唯讀,並在該伺服器上啟用群組複寫成員動作 mysql_start_failover_channels_if_primary,以便為 ClusterSet 複寫通道上的複本啟用非同步連線容錯移轉。

    • 將目標叢集設定為 ClusterSet 元資料中的主要叢集,並將舊的主要叢集變更為複本叢集。

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

  7. 如果您有任何 MySQL Router 執行個體要切換以鎖定新的主要叢集,請立即執行此操作。例如

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

    在此範例中,myclustersetClusterSet 物件的變數,Rome1 是 MySQL Router 執行個體的名稱,而 clustertwo 是要鎖定的特定叢集的名稱。完成後,發出 clusterSet.routingOptions() 命令,以檢查所有 MySQL Router 執行個體現在是否正確路由。

  8. 現在您可以處理舊的主要叢集來修復問題或執行維護。如果您在切換過程中必須將任何複本叢集設為失效,您也可以修復這些叢集並將它們重新新增至 InnoDB ClusterSet。第 8.9 節「InnoDB ClusterSet 修復和重新加入」說明如何修復叢集的問題、如何將叢集重新加入 InnoDB ClusterSet,以及如何再次將叢集設為主要叢集。