Documentation Home
MySQL 外壳 8.0  / 第 8 章 MySQL InnoDB ClusterSet  /  8.7 InnoDB ClusterSet控制切换

8.7 InnoDB ClusterSet控制切换

受控的切换使选定的副本集群成为 InnoDB ClusterSet 部署的主集群。在受控切换过程中,数据一致性得到保证。该过程验证所选副本集群是否与主集群同步(如果存在复制延迟,这可能意味着短暂的等待),然后使该集群成为 InnoDB ClusterSet 的主集群。原始主集群降级为工作的只读副本集群。然后,如有必要,您可以使原始主服务器脱机,修复任何问题,并在 InnoDB ClusterSet 部署中将其恢复运行。

如果 InnoDB ClusterSet 部署中的主集群运行正常,请遵循受控切换程序,但您需要进行维护或修复一些小问题以改进主集群的功能。 当您使用MySQL Shell 中 OK 的 AdminAPI 命令检查时 ,运行正常的主集群具有全局状态。clusterSet.status()

如果主集群NOT_OK在 InnoDB ClusterSet 部署中无法正常运行(具有全局状态),请首先尝试通过 MySQL Shell 使用 AdminAPI 修复任何问题。例如,如果主集群丢失了仲裁,则可以使用 cluster.forceQuorumUsingPartitionOf 命令将其恢复。有关执行此操作的说明,请参阅 第 8.9 节,“InnoDB ClusterSet 修复和重新加入”

如果您无法通过使用主集群来解决问题(例如,因为您无法联系它),则需要执行紧急故障转移。紧急故障转移是为主集群突然不可用时的灾难恢复而设计的。该过程存在丢失事务和为 InnoDB ClusterSet 造成裂脑情况的风险。如果您确实需要执行紧急故障转移,请按照 第 8.8 节“InnoDB ClusterSet 紧急故障转移”中的过程进行操作,以确保风险得到管理。

该图显示了 InnoDB ClusterSet 部署示例中受控切换的影响。罗马数据中心的主集群需要维护,因此进行了控制切换,使布鲁塞尔数据中心的副本集群成为 InnoDB ClusterSet 部署的主集群,并将罗马集群降级为副本。罗马集群上的 ClusterSet 复制通道已被受控切换过程激活,它正在从布鲁塞尔集群复制事务。现在罗马集群是一个副本集群,如果需要执行维护工作,成员服务器或整个集群可以安全地脱机。

图 8.2 InnoDB ClusterSet 切换

罗马数据中心的 InnoDB 集群现在是副本集群,布鲁塞尔数据中心的 InnoDB 集群现在是主集群。 异步复制通道现在正在将事务从布鲁塞尔集群发送到罗马集群。 以主集群或 Brussels 集群为目标的 MySQL Router 实例正在向 Brussels 集群发送流量。 专门针对 Rome 集群的实例可以继续向其发送流量,因为它只发送读取流量。

示例 InnoDB Cluster 部署中的 MySQL Router 实例设置为跟随主节点,已将读写流量路由到现在是主节点的 Brussels 集群。当它是副本集群时按名称将读取流量路由到 Brussels 集群的 MySQL Router 实例继续将流量路由到它,并且不受集群现在是主集群而不是副本集群这一事实的影响。同样,按名称将读取流量路由到 Rome 集群的 MySQL Router 实例可以继续执行此操作,因为副本集群仍然接受读取流量。

要对主 InnoDB Cluster 执行受控切换,请遵循以下过程:

  1. 使用 MySQL Shell,使用 InnoDB Cluster 管理员帐户(使用创建 cluster.setupAdminAccount())连接到主集群或其中一个副本集群中的任何成员服务器。您还可以使用 InnoDB Cluster 服务器配置帐户,该帐户也具有所需的权限。使用或 命令获取 ClusterSet对象 。使用 InnoDB Cluster 管理员帐户或服务器配置帐户很重要,这样存储在 对象中的默认用户帐户具有正确的权限。例如: dba.getClusterSet()cluster.getClusterSet()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 Cluster 管理员帐户的用户名。

    • 127.0.0.1:3310 是成员服务器实例的主机和端口,如 cluster.status() 命令所示。

    • 返回的ClusterSet对象被分配给变量myclusterset

  2. clusterSet.status() 使用MySQL Shell 中 的 AdminAPI 命令检查整个 InnoDB ClusterSet 部署的状态 。使用该extended 选项查看部署中所有集群的详细信息,并检查是否存在任何问题。例如:

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

    有关输出的解释,请参阅 第 8.6 节,“InnoDB ClusterSet 状态和拓扑”

  3. 确定可以作为主集群接管的合适的副本集群。副本集群是否有资格进行受控切换取决于其全局状态,如以下 clusterSet.status() 命令所报告:

    表 8.1 按状态允许的集群操作

    ClusterSet 中的 InnoDB Cluster 全局状态 可路由 受控切换 紧急故障转移
    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. clusterSet.routingOptions() 通过在连接到 InnoDB ClusterSet 部署中的任何成员服务器时在 MySQL Shell 中 发出命令,检查为每个 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() 命令,命名将接管的副本集群作为新的主集群。ClusterSet 将您使用 InnoDB Cluster 管理员帐户检索 到的对象与dba.getClusterSet()or 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,以防止在切换期间进一步更改。Group Replication 成员操作 mysql_disable_super_read_only_if_primary 已禁用,因此 super_read_only在故障转移后仍保持设置状态。

    • 协调当前主集群和副本集群之间视图更改事件的差异,以便 GTID 集相同。这些 Group Replication 内部事务由 group_replication_view_change_uuid 系统变量指定的 UUID 标识。MySQL Shell 在所有副本集群上注入空事务以匹配主集群上的视图更改事件。

    • 更新所有副本集群上的 ClusterSet 复制通道,以从目标集群复制为新的主集群。

    • 在目标集群的主服务器上禁用super_read_only ,并启用组复制成员操作 mysql_disable_super_read_only_if_primary 来处理对该集群中主服务器的任何更改。

    • 在旧主集群的主服务器上禁用 Group Replication 成员操作 mysql_disable_super_read_only_if_primary ,使其保持只读状态,并 mysql_start_failover_channels_if_primary 在该服务器上启用 Group Replication 成员操作,以便为 ClusterSet 复制通道上的副本启用异步连接故障转移。

    • 将目标集群设置为 ClusterSet 元数据中的主集群,并将旧的主集群更改为副本集群。

  6. 使用该选项再次发出 clusterSet.status() 命令extended,以验证 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,以及如何使集群再次成为主集群。