Documentation Home
MySQL 外壳 8.0  / 第 8 章 MySQL InnoDB ClusterSet  /  8.8 InnoDB ClusterSet 紧急故障转移

8.8 InnoDB ClusterSet 紧急故障转移

紧急故障转移使选定的副本集群成为 InnoDB ClusterSet 部署的主要 InnoDB 集群。当当前主集群不工作或无法联系时,可以使用此过程。在紧急故障转移过程中,数据的一致性是无法保证的,所以为了安全起见,在故障转移过程中,原主集群被标记为失效。如果原来的主集群保持联机状态,那么只要可以联系到它,就应该立即将其关闭。如果您可以解决问题,您可以修复无效的主集群并将其重新加入 InnoDB ClusterSet 拓扑。

当 InnoDB ClusterSet 部署中的主 InnoDB Cluster 出现问题或者您无法访问它时,不要立即实施到副本集群的紧急故障转移。相反,您应该始终从尝试修复当前活动的主集群开始。

重要的

为什么不只是故障转移?  InnoDB ClusterSet 拓扑中的副本集群正在尽最大努力使自己与主集群保持同步。但是,根据事务量以及主集群和副本集群之间网络连接的速度和容量,副本集群在接收事务和将更改应用于其数据方面可能落后于主集群。这称为复制滞后。在大多数复制拓扑中,一些复制滞后是可以预料的,并且在集群在地理上分散并且在不同数据中心的 InnoDB ClusterSet 部署中很可能。

此外,主集群有可能通过网络分区与 InnoDB ClusterSet 拓扑的其他元素断开连接,但仍保持在线状态。如果发生这种情况,一些副本集群可能会留在主集群中,一些实例和客户端应用程序可能会继续连接到主集群并应用事务。在这种情况下,InnoDB ClusterSet 拓扑的分区区域开始彼此不同,每组服务器上都有不同的事务集。

当存在复制滞后或网络分区时,如果触发到副本集群的紧急故障转移,则主集群上任何未复制或发散的事务都有丢失的风险。在网络分区的情况下,故障转移会造成脑裂情况,拓扑的不同部分具有不同的事务集。因此,在触发紧急故障转移之前,您应该始终尝试修复或重新连接主集群。如果主集群无法足够快地修复或无法访问,您可以继续进行紧急故障转移。

该图显示了 InnoDB ClusterSet 部署示例中紧急故障转移的影响。罗马数据中心的主集群已经下线,因此进行了紧急故障转移,使布鲁塞尔数据中心的副本集群成为InnoDB ClusterSet部署的主InnoDB集群。Rome 集群已被标记为无效,其在 InnoDB ClusterSet 部署中的状态已降级为副本集群,尽管它目前无法从 Brussels 集群复制事务。

图 8.3 InnoDB ClusterSet 故障转移

罗马数据中心的InnoDB集群现已下线失效,布鲁塞尔数据中心的InnoDB集群为主集群。 两者之间的异步复制没有发生,因为 Rome 集群不可用。 以主集群或 Brussels 集群为目标的 MySQL Router 实例正在向 Brussels 集群发送流量。 专门针对 Rome 集群的实例无法向该集群发送流量。

设置为跟随主节点的 MySQL Router 实例已将读写流量路由到现在是主节点的 Brussels 集群。当它是副本集群时按名称将读取流量路由到 Brussels 集群的 MySQL Router 实例继续将流量路由到它,并且不受集群现在是主集群而不是副本集群这一事实的影响。但是,按名称将读取流量路由到 Rome 集群的 MySQL Router 实例目前无法向那里发送任何流量。本例中的报告应用程序在本地数据中心离线时不需要报告,但如果应用程序仍然需要运行,

要为主 InnoDB Cluster 执行紧急故障转移,请遵循以下过程:

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

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

    mysql-js> \connect admin2@127.0.0.1:4410
    Creating a session to 'admin2@127.0.0.1:4410'
    Please provide the password for 'admin2@127.0.0.1:4410': ********
    Save password for 'admin2@127.0.0.1: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:admin2@127.0.0.1:4410>
    
    mysql-js> myclusterset = dba.getClusterSet()
    <ClusterSet:testclusterset>
  2. clusterSet.status() 使用MySQL Shell 中 的 AdminAPI 函数检查整个部署的状态 。使用该extended 选项可以准确查看问题出在哪里和出什么问题。例如:

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

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

  3. InnoDB Cluster 可以容忍一些问题并且运行良好以继续作为 InnoDB ClusterSet 部署的一部分。OK当您使用 clusterSet.status() 命令检查时,运行正常的主集群具有全局状态 。例如,如果集群中的一个成员服务器脱机,即使该服务器是主服务器,底层的 Group Replication 技术也可以处理这种情况并重新配置自身。

    如果根据报告的状态,主集群在 InnoDB ClusterSet 部署中仍然可以正常运行,但您需要进行维护或修复一些小问题以提高主集群的功能,您可以进行受控切换到副本集群。然后,如有必要,您可以使主集群脱机,修复任何问题,并在 InnoDB ClusterSet 部署中将其恢复运行。有关执行此操作的说明,请参阅 第 8.7 节,“InnoDB ClusterSet 控制切换”

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

  5. 如果您无法执行受控切换,并且无法通过使用主集群来足够快地解决问题(例如,因为您无法联系它),请继续进行紧急故障转移。首先确定一个合适的副本集群,可以接管为主集群。副本集群是否有资格进行紧急故障转移取决于其全局状态,如以下 clusterSet.status() 命令所报告:

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

    ClusterSet 中的 InnoDB Cluster 全局状态 可路由 受控切换 紧急故障转移
    OK 是的 是的 是的
    OK_NOT_REPLICATING 是,如果按名称指定为目标集群 是的 是的
    OK_NOT_CONSISTENT 是,如果按名称指定为目标集群 是的
    OK_MISCONFIGURED 是的 是的 是的
    NOT_OK
    INVALIDATED 是,如果按名称指定为目标集群并且 accept_ro设置了路由策略
    UNKNOWN Connected Router 实例可能仍在将流量路由到集群

    您选择的副本集群必须在所有可访问的副本集群中具有最新的事务集(GTID 集)。如果多个副本集群符合紧急故障转移的条件,请检查每个集群的复制滞后(显示在 clusterSet.status() 命令的扩展输出中)。选择复制滞后最少的副本集群,因此它应该有最多的事务。紧急故障转移过程检查当前可访问的所有副本集群的 GTID 集,并告诉您另一个集群是否更新,以便您可以再次尝试使用该集群。

  6. 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 实例都设置为跟随主 ( "target_cluster": "primary"),流量将在故障转移后的几秒钟内自动重定向到新的主集群。如果没有为 MySQL Router 实例显示路由选项,如上例中的"target_cluster"for Rome2,则意味着该实例没有设置该策略,它遵循全局策略。

    如果任何实例设置为按名称 ( ) 定位当前主集群,它们将不会将流量重定向到新的主集群。当主集群不工作时,该 命令不能用于更改路由选项,因此在故障转移到新的主集群完成之前,您不能重定向由该 MySQL Router 实例处理的流量。 "target_cluster": "name_of_primary_cluster"clusterSet.setRoutingOption()

  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 选项命名任何无法访问或不可用的副本集群。这些将在故障转移过程中被标记为无效。如果在此过程中发现任何您未命名的无法访问或不可用的副本集群,则会取消故障转移。在这种情况下,您必须修复并重新加入副本集群,然后重试该命令,或者在您重试该命令时在此选项上命名它们,并在稍后修复它们。

    当您发出 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. 使用该选项再次发出 clusterSet.status() 命令extended,以验证 InnoDB ClusterSet 部署的状态。

  11. 如果您能够再次联系到旧的主集群,请首先确保没有应用程序流量路由到它,然后将其脱机。然后按照 第 8.9 节“InnoDB ClusterSet 修复和重新加入”中的过程检查事务并决定如何安排 InnoDB ClusterSet 拓扑。

    在紧急故障转移之后,存在事务集在 ClusterSet 的各个部分之间不同的风险,您必须隔离集群以防止写入流量或所有流量。有关更多详细信息,请参阅 InnoDB ClusterSet 中的防护集群

    如果在切换过程中必须使任何副本集群无效,并且当您能够再次联系它们时,您可以使用 第 8.9 节“InnoDB ClusterSet 修复和重新加入”中的过程来修复它们并将它们添加回 InnoDB集群集。