受控切换使选定的副本集群成为 InnoDB ClusterSet 部署的主集群。在受控切换过程中,确保了数据的一致性。该过程验证所选副本集群是否与主集群同步(如果存在复制延迟,这可能意味着需要短时间的等待),然后使该集群成为 InnoDB ClusterSet 的主集群。原始主集群降级为工作的只读副本集群。然后,如果需要,您可以使原始主集群脱机,修复任何问题,并使其在 InnoDB ClusterSet 部署中重新运行。
如果 InnoDB ClusterSet 部署中的主集群运行正常,但您需要进行维护或修复一些小问题以改进主集群的功能,请遵循受控切换程序。当您在 MySQLShell 中使用 AdminAPI 的 clusterSet.status()
命令检查时,运行正常的主集群的全局状态为 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 切换
示例 InnoDB Cluster 部署中的 MySQL 路由器实例被设置为跟随主集群,并将读写流量路由到布鲁塞尔集群,而布鲁塞尔集群现在是主集群。MySQL 路由器实例在复制集群时按名称将读取流量路由到布鲁塞尔集群,并继续将流量路由到该集群,并且不受该集群现在是主集群而不是复制集群这一事实的影响。类似地,通过名称将读取流量路由到 Rome 集群的 MySQL Router 实例可以继续这样做,因为副本集群仍然接受读取流量。
要对主 InnoDB Cluster 进行受控切换,请遵循以下步骤:
-
使用 MySQL Shell, 使用 InnoDB Cluster 管理员帐户(使用
cluster.setupAdminAccount()
创建)连接到主集群或副本集群中的任何成员服务器。您也可以使用 InnoDB Cluster 服务器配置帐户,该帐户也具有所需的权限。使用dba.getClusterSet()
或cluster.getClusterSet()
命令获取 ClusterSet 对象。使用 InnoDB Cluster 管理员帐户或服务器配置帐户非常重要,以便存储在 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 的连接字符串。- admin2 是 InnoDB Cluster 管理员帐户的用户名。
- 127.0.0.1:3310 是成员服务器实例的主机和端口,如
cluster.status()
命令所示。 - 将返回的 ClusterSet 对象分配给 myclusterset 变量。
-
在 MySQL Shell 中使用 AdminAPI 的
clusterSet.status()
命令检查整个 InnoDB ClusterSet 部署的状态。使用extended
选项查看部署中所有集群的详细信息,并检查是否存在任何问题。例如:mysql-js> myclusterset.status({extended: 1})
有关输出的说明,请参阅 第8.6节 “InnoDB ClusterSet 的状态和拓扑”。
-
确定可以作为主集群来接管的合适的副本集群。副本集群的受控切换资格取决于其全局状态,如
clusterSet.status()
命令所报告的:
表 8.1 允许的集群操作(按状态)ClusterSet 内的 InnoDB Cluster 全局状态 是否可路由 受控切换 紧急故障切换 OK 是 是 是 OK_NOT_REPLICATING 是,如果使用名称指定目标集群 是 是 OK_NOT_CONSISTENT 是,如果使用名称指定目标集群 否 是 OK_MISCONFIGURED 是 是 是 NOT_OK 否 否 否 INVALIDATED 是,如果使用名称指定目标集群并且设置 accept_ro
路由策略否 否 UNKNOWN 已连接的MySQL路由器实例可能仍在将流量路由到该集群 否 否 全局状态为
OK_NOT_CONSISTENT
的副本集群,在该集群上的一组事务( GTID 集)与主集群上的 GTID 集不一致。InnoDB ClusterSet 不允许受控切换到在该状态下的集群,因为客户端会访问不正确的数据。如果集群具有可选项中最新的一组事务,则可以进行紧急故障切换。 -
当连接到 InnoDB ClusterSet 部署中的任何成员服务器时,通过在 MySQL Shell 中执行
clusterSet.routingOptions()
命令,检查为每个 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 路由器实例向 InnoDB ClusterSet 部署中当前的主集群发送流量。如果所有 MySQL 路由器实例都设置为遵循主集群(
"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'.
在本例中,myclusterset 是 ClusterSet 对象的变量,Rome1 是 MySQL 路由器实例的名称。
或者,您可以指定将作为主集群来接管的副本集群,在这种情况下,在切换发生后,当您验证它是否生效时,设置选项(
"target_cluster": "name_of_new_primary_cluster"
)。 -
执行
clusterSet.setPrimaryCluster()
命令,将要接管的副本集群指定为新的主集群。使用使用 InnoDB Cluster 管理员帐户检索的 ClusterSet 对象,并使用dba.getClusterSet()
或clusterSet.setPrimaryCluster()
命令。例如: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()
命令时,MySQLShell 会检查目标副本集群是否符合接管主集群的要求,如果不符合,则返回错误。如果目标副本集群满足要求,MySQL Shell 将执行以下任务:- 检查未使用
invalidateReplicaClusters
指定的任何无法访问或不可用的副本集群。 - 通过应用来自主集群的任何未完成事务,等待目标副本集群与当前主群集同步。如果
timeout
选项设置的超时在副本集群完成应用事务之前过期,则切换将被取消。 - 通过执行
FLUSH TABLES WITH READ LOCK
语句并在所有成员服务器上设置super_read_only
1 系统变量来锁定当前主集群,以防止在切换期间发生进一步更改。组复制成员操作mysql_disable_super_read_only_if_primary
已禁用,以便在故障切换后super_read_only
保持设置。 - 协调当前主集群和副本集群之间视图更改事件的差异,以便 GTID 集相同。这些组复制内部事务由
group_replication_view_change_uuid
系统变量指定的 UUID 确定。MySQL Shell 在所有副本集群上注入空事务,以匹配主集群上的视图更改事件。 - 更新从以新的主集群作为目标集群、复制到所有副本集群上的 ClusterSet 复制通道。
- 在目标集群的主服务器上禁用
super_read_only
, 并启用组复制成员操作mysql_disable_super_read_only_if_primary
来处理对该集群中主服务器的任何更改。 - 在旧主集群的主服务器上禁用组复制成员操作
mysql_disable_super_read_only_if_primary
, 使其保持只读状态,并在该服务器上启用组复制成员动作mysql_start_failover_channels_if_parimary
, 以便为 ClusterSet 复制通道上的副本启用异步连接故障切换。 - 将目标集群设置为 ClusterSet 元数据中的主集群,并将旧的主群集更改为副本集群。
- clusterName 参数是必需的,它指定用于 InnoDB ClusterSet 中副本集群的标识符,如
-
再次使用
extended
选项执行clusterSet.status()
命令,来验证 InnoDB ClusterSet 部署的状态。 -
如果您有任何 MySQL 路由器实例要切换到新的主集群,请立即切换。例如:
mysql-js> myclusterset.setRoutingOption('Rome1', 'target_cluster', 'clustertwo') Routing option 'target_cluster' successfully updated in router 'Rome1'.
在本例中,myclusterset 是 ClusterSet 对象的变量,Rome1 是 MySQL 路由器实例的名称,clustertwo 是目标的特定集群的名称。完成后,执行
clusterSet.routingOptions()
命令,检查所有 MySQL 路由器实例现在是否正确路由。 -
现在,您可以使用旧的主集群来修复问题或执行维护。如果您必须在切换过程中使任何副本集群失效,那么您也可以修复这些集群,并将它们重新添加到 InnoDB ClusterSet 中。第 8.9 节 “InnoDB ClusterSet 的修复和重新加入” 解释了如何修复集群问题,如何将集群重新加入 InnoDB ClusterSet ,以及如何将集群再次转变为主集群。
super_read_only
: https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_super_read_only ↩︎