MySQL Shell 9.0  /  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 Cluster 部署中設定為追蹤主要叢集的 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": "主要叢集名稱"),它們將不會將流量重新導向至新的主要叢集。在這種情況下,如果適用於應用程式,您可以使用 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": "新主要叢集名稱")。

  5. 發出 clusterSet.setPrimaryCluster() 命令,指定將接管成為新主要叢集的複本叢集。使用您使用 InnoDB 叢集管理員帳戶,透過 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 系統變數來鎖定目前的主要叢集,以防止在切換期間進一步變更。停用 Group Replication 成員動作 mysql_disable_super_read_only_if_primary,因此在容錯移轉之後,super_read_only 會保持設定。

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

      注意:

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

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

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

    • 在舊主要叢集的主要伺服器上停用 Group Replication 成員動作 mysql_disable_super_read_only_if_primary,使其保持唯讀,並在該伺服器上啟用 Group Replication 成員動作 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,以及如何再次將叢集設為主要叢集。