MySQL Shell 9.0  /  ...  /  从重大故障中重启集群

7.8.3 从重大故障中重启集群

如果您的集群遇到完全中断,您可以使用 dba.rebootClusterFromCompleteOutage() 重新配置它。此操作使您可以连接到集群的其中一个 MySQL 实例,并使用其元数据恢复集群。

完全中断意味着组复制已在所有成员实例上停止。

注意

请确保在运行 dba.rebootClusterFromCompleteOutage() 之前启动所有集群成员。如果任何集群成员不可达,该命令将失败。

如果集群已失效并且是 ClusterSet 的成员,则忽略此检查。

连接到最新的实例并运行以下命令

  JS> var cluster = dba.rebootClusterFromCompleteOutage()

如果所有成员都具有相同的 GTID 集,则当前连接的成员将成为主成员。请参阅 使用 rebootClusterFromCompleteOutage 选择主节点

dba.rebootClusterFromCompleteOutage() 操作遵循以下步骤以确保正确重新配置集群

  • 从当前实例检索集群元数据和集群拓扑。

  • 如果某个集群成员处于 RECOVERING 或 ERROR 状态,并且所有其他成员都处于 OFFLINE 或 ERROR 状态,则 dba.rebootClusterFromCompleteOutage() 会尝试在该成员上停止组复制。如果组复制无法停止,则该命令将停止并显示错误。

  • 检查 MySQL Shell 当前连接到的实例上的 InnoDB 集群元数据,以查看其是否包含 GTID 超集。如果当前连接的实例不包含 GTID 超集,则操作将中止并显示该信息。

    请参阅 GTID 超集

  • 如果实例包含 GTID 超集,则将根据存储在该实例中的元数据恢复集群。

  • MySQL Shell 检查集群的哪些实例当前可达,如果任何成员当前不可达,则失败。

    注意

    可以使用 force 选项绕过此检查。这将使用剩余的可联系成员重启集群。

    请参阅 强制选项

  • 同样,MySQL Shell 会检测当前不可达的实例。如果以前的成员当前不可达,则无法在 dba.rebootClusterFromCompleteOutage() 命令中将它们添加到集群或从集群中删除。

  • 如果在集群的主实例上启用了单主模式,则会禁用 super_read_only

GTID 超集

要重启集群,您必须连接到具有 GTID 超集的成员,这意味着在中断之前应用了最多事务的实例。

要确定哪个成员具有 GTID 超集,请执行以下操作之一

  • 连接到实例并使用 dryRun: true 运行 dba.rebootClusterFromCompleteOutage()。生成的报告返回类似于以下内容的信息:。

                  Switching over to instance '127.0.0.1:4001' to be used as seed.

    这表示具有 GTID 超集的成员。

    对具有较低 GTID 集的成员运行 dba.rebootClusterFromCompleteOutage() 会导致错误。

  • 依次连接到每个实例,并在 SQL 模式下运行以下命令

    SHOW VARIABLES LIKE 'gtid_executed';

    应用了最大 GTID 集 事务的实例包含 GTID 超集。

注意

可以通过使用 force 选项运行 dba.rebootClusterFromCompleteOutage() 来覆盖此行为,并使用具有较低 GTID 集的实例。

这会使选定的成员成为主成员,并丢弃未包含在选定成员的 GTID 集中的任何事务。

如果此过程失败,并且集群元数据已严重损坏,则您可能需要删除元数据并从头开始重新创建集群。您可以使用 dba.dropMetadataSchema() 删除集群元数据。

警告

dba.dropMetadataSchema() 方法应仅在无法恢复集群时才使用,作为最后的手段。它无法撤消。

如果您在集群中使用 MySQL Router,则在删除元数据时,所有当前连接都将断开,并且禁止建立新连接。这会导致完全中断。

选项

dba.rebootClusterFromCompleteOutage() 具有以下选项

  • force: true | false (默认值):如果为 true,即使无法访问集群的某些成员,或者所选主实例的 GTID_SET 不同或较低,也必须执行该操作。请参阅 强制选项

  • dryRun: true | false (默认值):执行命令的所有验证和步骤,但不进行任何更改。完成后会显示报告。请参阅 测试 rebootClusterFromCompleteOutage

  • primary:表示必须选择为主节点的实例的实例定义。请参阅 使用 rebootClusterFromCompleteOutage 选择主节点

  • switchCommunicationStack: mysql | xcom:重启后集群将使用的组复制协议栈。请参阅 第 7.5.9 节“配置组复制通信堆栈”

  • ipAllowList:使用 XCOM 协议栈时允许连接到实例以进行组复制流量的主机列表。

  • localAddress:字符串值,表示使用 XCOM 协议栈时要使用的组复制本地地址,而不是自动生成的地址。

强制选项

force 选项使您可以忽略集群成员的可用性或所选成员中 GTID 集的差异,并重启集群。

例如,重启集群 myCluster

  JS> var cluster = dba.rebootClusterFromCompleteOutage("myCluster",{force: true})

在以下情况下不允许使用 force 选项

  • 如果集群属于 ClusterSet 并且已失效,或者主集群的全局状态不是 OK,

  • 集群属于 ClusterSet,是主集群,并且已失效。

无法使用 rebootClusterFromCompleteOutage 添加或重新加入实例。如果您使用 force 忽略不可达的成员并重启集群,则必须使用 cluster.rejoinInstance() 将不可达的成员添加到集群。

使用 rebootClusterFromCompleteOutage 选择主节点

您可以通过以下方式之一定义集群主节点

  • dba.rebootClusterFromCompleteOutage() 命令中定义 primary 选项。

    例如,重启集群 myCluster 并将本地机器上端口 4001 上运行的成员设置为主要成员

    var cluster = dba.rebootClusterFromCompleteOutage("myCluster",{primary: "127.0.0.1:4001"})

  • 通过在 GTID 集低于另一个成员的集群成员上将 primary 选项与 force 选项一起使用。

测试 rebootClusterFromCompleteOutage

您可以使用 dryRun 选项测试更改。此选项将验证命令及其选项,并生成结果日志。如果提议的更改有问题,则会引发异常。

以下示例显示了重启集群 myCluster 的 dry run,将主节点设置为在端口 4001 上运行的本地成员,以及它返回的日志消息

JS > var cluster = dba.rebootClusterFromCompleteOutage("myCluster",{primary: "127.0.0.1:4001", dryRun: true})

NOTE: dryRun option was specified. Validations will be executed, but no changes will be applied.
Cluster instances: '127.0.0.1:4000' (OFFLINE), '127.0.0.1:4001' (OFFLINE), '127.0.0.1:4002' (OFFLINE)
Switching over to instance '127.0.0.1:4001' to be used as seed.
dryRun finished.

ClusterSet 和 ReplicaSet 的注意事项

rebootClusterFromCompleteOutage 执行以下检查,并在集群不满足要求时生成警告

  • 确认副本集群没有被强制从 ClusterSet 中移除。

  • 确认 ClusterSet 的主集群可达。

  • 检查集群中是否存在不是视图更改日志事件 (VCLE) 的错误事务。请参阅 分布式恢复的工作原理

  • 确认集群的已执行事务集 (GTID_EXECUTED) 不为空。

该命令自动将副本集群重新加入 ClusterSet,确保为所有集群成员配置了 ClusterSet 复制通道。

切换通信堆栈

您可以在 dba.rebootClusterFromCompleteOutage() 操作期间切换通信堆栈。

例如:

        js> dba.rebootClusterFromCompleteOutage("testcluster", {switchCommunicationStack: "mysql"})

MYSQL 协议切换到 XCOM 需要为 localAddress 提供额外的网络地址,并且可能还需要您定义 ipAllowList 值。