MySQL Shell 9.0  /  MySQL InnoDB ClusterSet  /  InnoDB ClusterSet 控制切换

8.7 InnoDB ClusterSet 控制切换

控制切换将选定的副本集群变为 InnoDB ClusterSet 部署的主集群。在控制切换过程中,会确保数据一致性。该过程会验证选定的副本集群是否与主集群同步(如果存在复制延迟,则可能需要短暂等待),然后将该集群变为 InnoDB ClusterSet 的主集群。原始主集群会被降级为工作中的只读副本集群。然后,您可以根据需要将原始主集群脱机,修复任何问题,并将其重新加入到 InnoDB ClusterSet 部署中。

如果 InnoDB ClusterSet 部署中的主集群运行正常,但您需要进行维护或修复一些小问题以改善主集群的功能,则请遵循控制切换过程。运行正常的集群在您使用 AdminAPI 的 clusterSet.status() 命令在 MySQL Shell 中检查它时,其全局状态为 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 [email protected]:3310
    Creating a session to '[email protected]:3310'
    Please provide the password for '[email protected]:3310': ********
    Save password for '[email protected]: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:[email protected]: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. 使用 AdminAPI 的 clusterSet.status() 命令在 MySQL Shell 中检查整个 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. 检查为每个 MySQL Router 实例设置的路由选项以及 InnoDB ClusterSet 部署的全局策略,方法是在 MySQL Shell 中连接到 InnoDB ClusterSet 部署中的任何成员服务器时,发出 clusterSet.routingOptions() 命令。例如

    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 集群管理员帐户检索的 ClusterSet 对象,以及 dba.getClusterSet()cluster.getClusterSet() 命令。例如

    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,以及如何将集群再次设置为主集群。