受控切换使选定的副本集群成为 InnoDB ClusterSet 部署的主集群。在受控的切换过程中,保证了数据的一致性。该过程验证所选的副本集群是否与主集群同步(如果存在复制滞后,这可能意味着短暂的等待),然后使该集群成为 InnoDB ClusterSet 的主集群。原始主集群被降级为工作只读副本集群。然后,您可以根据需要使原始主数据库脱机,修复任何问题,然后将其在 InnoDB ClusterSet 部署中恢复运行。
如果 InnoDB ClusterSet 部署中的主集群运行良好,但需要进行维护或修复一些小问题以改善主集群的功能,请遵循受控切换过程。 当您在 MySQL Shell 中 OK
使用 AdminAPI 命令检查时, 运行正常的主集群具有全局状态。*
clusterSet*.status()
如果主集群在 InnoDB ClusterSet 部署中无法正常运行(全局状态为NOT_OK
),请首先尝试通过 MySQL Shell 使用 AdminAPI 修复任何问题。例如,如果主集群丢失仲裁,可以使用 *
cluster*.forceQuorumUsingPartitionOf
命令恢复。有关执行此操作的说明,请参阅 第 8.9 节 “InnoDB ClusterSet 修复和重新加入”。
如果无法通过使用主集群来解决问题(例如,因为无法联系它),则需要执行紧急故障转移。紧急故障转移旨在当主集群突然不可用时进行灾难恢复。该过程存在丢失事务并为 InnoDB ClusterSet 创建脑裂情况的风险。如果确实需要执行紧急故障转移,请按照 第 8.8 节“InnoDB ClusterSet 紧急故障转移”中的过程进行操作,以确保风险得到管理。
该图显示了 InnoDB ClusterSet 部署示例中受控切换的效果。罗马数据中心的主集群需要维护,因此进行了受控切换,使布鲁塞尔数据中心的副本集群成为InnoDB ClusterSet部署的主集群,并将罗马集群降级为副本。罗马集群上的 ClusterSet 复制通道已通过受控切换过程激活,并且正在从布鲁塞尔集群复制事务。现在,Rome 集群是一个副本集群,如果需要执行维护工作,可以安全地将成员服务器或整个集群脱机。
图8.2 InnoDB ClusterSet切换
示例 InnoDB 集群部署中设置为跟随主集群的 MySQL Router 实例已将读写流量路由到现在作为主集群的布鲁塞尔集群。当布鲁塞尔集群是副本集群时,按名称将读取流量路由到布鲁塞尔集群的 MySQL Router 实例将继续将流量路由到该集群,并且不会受到该集群现在是主集群而不是副本集群这一事实的影响。同样,按名称将读取流量路由到 Rome 集群的 MySQL Router 实例可以继续执行此操作,因为副本集群仍然接受读取流量。
要对主 InnoDB Cluster 执行受控切换,请按照以下过程操作:
-
使用 MySQL Shell,使用 InnoDB Cluster 管理员帐户(使用 创建)连接到主集群或副本集群之一中的任何成员服务器
*
cluster*.setupAdminAccount()
。您还可以使用 InnoDB Cluster 服务器配置帐户,该帐户也具有所需的权限。ClusterSet
使用dba.getClusterSet()
或 命令获取 对象*
cluster*.getClusterSet()
。使用 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 to set one.mysql-js> myclusterset = dba.getClusterSet()
在这个例子中:
-
*
admin2*@*
127.0.0.1:3310*
是集群中任何在线成员服务器实例的类似 URI 的连接字符串。类似 URI 的连接字符串由以下元素组成:
-
*
admin2*
是 InnoDB Cluster 管理员帐户的用户名。 -
*
127.0.0.1:3310*
是成员服务器实例的主机和端口,如命令所示*
cluster*.status()
。 -
返回的
ClusterSet
对象被分配给变量myclusterset
。
-
-
使用 MySQL Shell 中的 AdminAPI 命令检查整个 InnoDB ClusterSet 部署的状态
*
clusterSet*.status()
。使用该extended
选项查看部署中所有集群的详细信息,并检查是否存在任何问题。例如:mysql-js> myclusterset.status({extended: 1})
有关输出的说明,请参见 第 8.6 节 “InnoDB ClusterSet 状态和拓扑”。
-
确定可以接管主集群的合适副本集群。副本集群是否有资格进行受控切换取决于其全局状态,如以下
*
clusterSet*.status()
命令所报告:表 8.1 允许的集群操作(按状态)
ClusterSet 中的 InnoDB 集群全局状态 可路由 受控切换 紧急故障转移 OK
是的 是的 是的 OK_NOT_REPLICATING
是,如果按名称指定为目标集群 是的 是的 OK_NOT_CONSISTENT
是,如果按名称指定为目标集群 不 是的 OK_MISCONFIGURED
是的 是的 是的 NOT_OK
不 不 不 INVALIDATED
是,如果按名称指定为目标集群并 accept_ro
设置路由策略不 不 UNKNOWN
连接的 MySQL Router 实例可能仍在将流量路由到集群 不 不 具有全局状态的副本集群
OK_NOT_CONSISTENT
在集群上有一组事务(GTID 集)与主集群上的 GTID 集不一致。InnoDB ClusterSet 不允许在此状态下对集群进行受控切换,因为客户端会访问不正确的数据。如果集群具有可用选项中最新的事务集,则可以进行紧急故障转移。 -
*
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'.
在此示例中,
*
myclusterset*
是对象的变量ClusterSet
,*
Rome1*
是 MySQL Router 实例的名称。或者,您可以指定将接管主集群的副本集群,在这种情况下,当您确认切换已正常工作时,请在切换发生后设置选项 ( )。
"target_cluster": "*
name_of_new_primary_cluster*"
-
发出
*
clusterSet*.setPrimaryCluster()
命令,将要接管的副本集群命名为新的主集群。使用ClusterSet
通过 InnoDB Cluster 管理员帐户检索的对象,以及dba.getClusterSet()
或*
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
,以防止切换期间发生进一步更改。组复制成员操作mysql_disable_super_read_only_if_primary
被禁用,以便super_read_only
在故障转移后保持设置状态。- 协调当前主集群和副本集群之间视图更改事件的差异,以使 GTID 集相同。这些组复制内部事务由系统变量指定的 UUID 标识
group_replication_view_change_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_primary
在该服务器上启用组复制成员操作,以便为 ClusterSet 复制通道上的副本启用异步连接故障转移。- 在 ClusterSet 元数据中将目标集群设置为主集群,并将旧的主集群更改为副本集群。
- 该*
-
*
clusterSet*.status()
使用该选项再次 发出 命令extended
,以验证 InnoDB ClusterSet 部署的状态。 -
如果您有任何 MySQL Router 实例需要切换到新的主集群,请立即执行此操作。例如:
mysql-js> myclusterset.setRoutingOption('Rome1', 'target_cluster', 'clustertwo')
Routing option 'target_cluster' successfully updated in router 'Rome1'.
在此示例中,
*
myclusterset*
是对象的变量ClusterSet
,*
Rome1*
是 MySQL Router 实例的名称,*
clustertwo*
是要定位的特定集群的名称。完成后,发出*
clusterSet*.routingOptions()
命令来检查所有 MySQL Router 实例现在是否都正确路由。 -
现在,您可以使用旧的主集群来修复问题或进行维护。如果您必须在切换过程中使任何副本集群失效,您也可以修复它们并将它们添加回 InnoDB ClusterSet。 第8.9节“InnoDB ClusterSet修复和重新加入”解释了如何修复集群问题,如何将集群重新加入InnoDB ClusterSet,以及如何使集群再次成为主集群。