MySQL Shell 8.4  /  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 路由器实例已将读写流量路由到布鲁塞尔集群,该集群现在是主集群。当布鲁塞尔集群还是副本集群时,通过名称将读流量路由到布鲁塞尔集群的 MySQL 路由器实例继续将其路由到该集群,并且不受集群现在是主集群而不是副本集群的影响。但是,通过名称将读流量路由到罗马集群的 MySQL 路由器实例目前无法向其发送任何流量。此示例中的报告应用程序不需要在本地数据中心离线时进行报告,但是如果应用程序仍然需要运行,则应更改 MySQL 路由器实例的路由选项,使其跟踪主集群或将流量发送到布鲁塞尔集群。

要对主 InnoDB 集群执行紧急故障转移,请遵循以下步骤

  1. 使用 MySQL Shell,使用 InnoDB 集群管理员帐户(使用 cluster.setupAdminAccount() 创建)连接到 InnoDB ClusterSet 部署中仍然活动的任何成员服务器。您也可以使用 InnoDB 集群服务器配置帐户,该帐户也具有所需的权限。

    建立连接后,使用 dba.getClusterSet()cluster.getClusterSet() 命令从该成员服务器获取 ClusterSet 对象。您之前从现在已离线的成员服务器中检索到的 ClusterSet 对象将不再起作用,因此您需要从在线服务器中再次获取它。重要的是使用 InnoDB 集群管理员帐户或服务器配置帐户,以便 ClusterSet 对象中存储的默认用户帐户具有正确的权限。例如

    mysql-js> \connect [email protected]:4410
    Creating a session to '[email protected]:4410'
    Please provide the password for '[email protected]:4410': ********
    Save password for '[email protected]: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:[email protected]:4410>
    
    mysql-js> myclusterset = dba.getClusterSet()
    <ClusterSet:testclusterset>
  2. 使用 AdminAPI 的 clusterSet.status() 函数在 MySQL Shell 中检查整个部署的状态。使用 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 路由器实例设置的路由选项以及 InnoDB ClusterSet 部署的全局策略。例如

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

    如果所有 MySQL 路由器实例都设置为跟踪主集群("target_cluster": "primary"),则流量将在故障转移后几秒钟内自动重定向到新的主集群。如果未为 MySQL 路由器实例显示路由选项,如上面的示例中 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。