7. MySQL InnoDB Cluster
MySQL InnoDB Cluster 为 MySQL 提供了完整的高可用解决方案。通过使用 MySQL Shell 附带的 AdminAPI,您可以轻松配置和管理一组至少 3 个 MySQL 服务器实例,以充当 InnoDB Cluster 集群。
InnoDB Cluster 中的每个 MySQL 服务器实例都运行 MySQL Group Replication,它提供了在 InnoDB Cluster 中复制数据的机制,并具有内置故障转移功能。 AdminAPI 消除了在 InnoDB Cluster中直接使用组复制的需要,但有关更多信息,请参阅组复制,其中解释了详细信息。从 MySQL 8.0.27 开始,您还可以设置 InnoDB ClusterSet(请参阅 第 8 章 MySQL InnoDB ClusterSet),通过将主 InnoDB Cluster 与其位于备用位置(如不同的数据中心)的一个或多个副本链接起来,为 InnoDB Cluster 部署提供容灾能力。
MySQL Router 可以根据您部署的集群自动配置其自身,将客户端应用透明地连接到 MySQL 服务器实例。如果服务器实例发生意外故障,集群会自动重新配置。在默认的 单主模式 下,InnoDB Cluster 有 1 个读写服务器实例,即主(Primary)实例。多个辅助服务器(Secondary)实例是主服务器实例的副本。如果主服务器发生故障,辅助服务器将自动提升为主服务器角色。 MySQL Router 检测到这变化会将客户端应用程序转发到新的主服务器。高级用户还可以将集群配置为具有多个主服务器。
下图显示了这些技术如何协同工作的概述:

:::alert-info
【Important】
InnoDB Cluster 不提供对 MySQL NDB Cluster 的支持。 NDB Cluster 依赖于 NDB 存储引擎以及一些特定于 NDB Cluster 的程序,这些程序未随 MySQL Server 8.0 提供; NDB 仅作为 MySQL NDB Cluster 发行版的一部分提供。此外,MySQL Server 8.0 附带的 MySQL server 二进制文件 (mysqld) 不能与 NDB Cluster 一起使用。有关 MySQL NDB Cluster 的更多信息,请参阅 MySQL NDB Cluster 8.0。MySQL Server Using InnoDB Compared with NDB Cluster 提供了有关 InnoDB 和 NDB 存储引擎之间的差异信息。
:::
7.1. InnoDB Cluster 要求
在安装 InnoDB Cluster 的生产部署之前,请确保您要使用的服务器实例满足以下要求。
InnoDB Cluster使用组复制,因此您的服务器实例必须满足相同的要求。请参阅 组复制 要求。AdminAPI提供dba.checkInstanceConfiguration()方法来验证MySQL实例是否满足组复制要求,并提供dba.configureInstance()方法来配置MySQL实例以满足要求。
:::alert-info
【Note】
使用沙盒(sandbox)部署时,MySQL 实例将被自动配置为满足组复制要求。
:::
- 用于组复制的数据以及用于
InnoDB Cluster的数据必须存储在InnoDB事务存储引擎中。使用其他存储引擎(包括临时MEMORY存储引擎)可能会导致组复制出现错误。在将MySQL实例与组复制和InnoDB集群一起使用之前,将其他存储引擎中的任何表转换为使用InnoDB。您可以通过在MySQL服务器实例上设置disabled_storage_engines(不支持动态修改)系统变量来阻止使用其他存储引擎,例如:
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
-
设置
InnoDB Cluster时,任何服务器实例上都不能有入站复制通道。正在采用的复制组上允许使用组复制自动创建的通道(group_replication_applier和group_replication_recovery)。除了使用AdminAPI管理的通道之外,InnoDB Cluster不支持手动配置的异步复制通道。如果您要将现有复制拓扑迁移到InnoDB Cluster部署,并且需要在设置过程中暂时跳过此验证,则可以在创建InnoDB Cluster时使用force选项来绕过它。 -
不得将
group_replication_tls_source设置为mysql_admin。 -
必须在与
InnoDB Cluster一起使用的任何MySQL实例上启用Performance Schema。 -
MySQL Shell使用的、用于配置InnoDB Cluster的脚本需要访问Python。在Windows上,MySQL Shell包含Python,无需用户配置。在Unix上,Python必须作为shell环境的一部分存在。要检查您的系统是否已正确配置Python,请执行以下操作:
$ /usr/bin/env python
如果 Python 解释器启动,则无需执行进一步操作。如果上一个命令失败,请在 /usr/bin/python 和您选择的 Python 二进制文件之间创建软链接。有关详细信息,请参阅支持的语言。
-
从
MySQL 8.0.17开始,每个MySQL实例必须在InnoDB Cluster中使用唯一的server_id。当您使用Cluster.addInstance(instance)添加成员时,如果实例的server_id已被集群中的实例使用,则操作将失败并报错。 -
从
MySQL 8.0.23开始,应将实例的SQL应用线程配置为并行。请参阅 第 7.5.6 节“配置并行复制应用线程”。 -
在为
InnoDB Cluster配置MySQL实例的过程中,自动配置了实例所需的大部分系统变量。但AdminAPI未配置transaction_isolation系统变量,这意味着它默认为REPEATABLE READ。这不会影响单主集群,但如果您使用多主集群,那么除非您的应用程序依赖REPEATABLE READ,否则我们建议使用READ COMMITTED隔离级别。请参阅 组复制限制。
7.2. 10.MySQL实例的相关配置选项,特别是组复制配置选项,必须位于单个选项文件中。InnoDB Cluster仅支持MySQL服务器实例的单个选项文件,不支持使用--defaults-extra-file选项指定附加选项文件。对于使用实例选项文件的任何AdminAPI操作,必须指定主文件。如果要对与InnoDB Cluster无关的配置选项使用多个选项文件,则必须手动配置这些文件,并确保多个选项文件可依据优先级正确更新这些配置,并确保相关InnoDB Cluster设置不会被额外的选项文件中的选项错误地覆盖。7.2.
7.2. InnoDB Cluster 限制
本节介绍 InnoDB Cluster 的已知限制。由于 InnoDB Cluster 使用组复制,您还应该了解其限制,请参阅 组复制限制。
:::alert-info
【Important】
由于元数据(metadata)查询中的错误,MySQL Shell 8.0.27 无法用于管理运行 MySQL Server 8.0.25 的 InnoDB Cluster。要解决此问题,请将 InnoDB Cluster 成员实例的 MySQL Server 升级到 8.0.26 或 8.0.27 版本,然后再将 MySQL Shell 8.0.27 与 InnoDB Cluster 一起使用。该问题将在 MySQL Shell 8.0.28 中得到修复。
:::
-
InnoDB Cluster不会管理手动配置的异步复制通道。组复制和AdminAPI不能确保异步复制在主服务器上处于活动(active)状态,并且状态不会跨实例复制。这可能会导致复制失效,并可能导致脑裂。仅InnoDB ClusterSet(从MySQL 8.0.27开始提供)支持从一个InnoDB Cluster复制到另一个InnoDB Cluster。InnoDB ClusterSet可管理从一个活动的RW InnoDB Cluster到多个RO InnoDB Cluster副本的复制。有关该解决方案的信息,请参阅 第 8 章 MySQL InnoDB ClusterSet。 -
InnoDB Cluster旨在部署在局域网中。在广域网上部署单个InnoDB Cluster对写入性能有显着影响。稳定且低延迟的网络对于InnoDB Cluster成员服务器使用底层组复制技术相互通信以达成事务共识非常重要。而InnoDB ClusterSet则被设计为跨多个数据中心部署,每个InnoDB Cluster都位于单个数据中心中,并通过异步复制通道将它们链接起来。有关该解决方案的信息,请参阅 第 8 章 MySQL InnoDB ClusterSet。 -
对于
AdminAPI操作,您只能使用TCP/IP连接和经典MySQL协议连接到InnoDB Cluster中的MySQL实例。AdminAPI操作不支持使用Unix套接字和命名管道,并且AdminAPI操作不支持使用X协议。同样的限制也适用于MySQL server实例本身之间的连接。
:::alert-info
【Note】
客户端应用程序可以使用 X 协议、Unix 套接字和命名管道来连接到 InnoDB Cluster 中的实例。本限制仅适用于使用 AdminAPI 命令的管理操作以及实例之间的连接。
:::
-
AdminAPI和InnoDB Cluster支持使用运行MySQL Server 5.7的实例。但是,这些实例还有其他限制,并且所描述的某些功能在您使用它们时不适用。”列出了其他限制 第 6.2.1 节“使用运行 MySQL 5.7 的实例 列除了其他限制。 -
使用多主模式时,不支持对在不同服务器上的同一对象发出的并行
DDL、DML语句。在对对象发出DDL语句期间,从不同的服务器实例对同一对象发出并行DML存在无法检测到在不同实例上执行DDL冲突的风险。有关详细信息,请参阅 组复制限制。
7.3. InnoDB Cluster 的用户账户
InnoDB Cluster 中的成员服务器使用 3 类的用户帐户:1)一个 InnoDB Cluster 服务器配置帐户用于配置 InnoDB Cluster 的服务器实例。2)可以在 InnoDB Cluster 搭建完成后,创建一个或多个 InnoDB Cluster 管理员账户,供管理员管理 MySQL 实例。3)可以为 MySQL Router 实例创建一个或多个 MySQL Router 帐户以连接到 InnoDB Cluster。
每个用户帐户必须存在于 InnoDB Cluster 中的所有成员服务器上,并且具有相同的用户名和密码。
InnoDB Cluster服务器配置帐户
该帐户用于创建和配置 InnoDB Cluster 的成员服务器。每台成员服务器只有一个服务器配置帐户。集群中的每台成员服务器必须使用相同的帐户名和密码。为此,您可以使用服务器上的 root 帐户,但如果这样做,集群中每个成员服务器上的 root 帐户必须具有相同的密码。出于安全考虑,不建议这样做。
首选方案是使用带有 clusterAdmin 选项的 dba.configureInstance() 命令创建 InnoDB Cluster 服务器配置帐户。为了获得更高的安全性,请在交互式提示符处指定密码,否则可使用 clusterAdminPassword 选项指定密码。在将成为 InnoDB Cluster 一部分的每个服务器实例(您连接的创建 InnoDB Cluster 的实例以及即将加入 InnoDB Cluster 的实例)上以相同的方式使用相同的用户名和密码创建相同的帐户。
dba.configureInstance() 命令自动授予帐户所需的权限。如果您愿意,可以手动设置该帐户,并授予其 第 7.3.1 节 手动配置 InnoDB Cluster 管理员帐户 中列出的权限。除了完整的 MySQL 管理员权限之外,该帐户还需要对 InnoDB Cluster 元数据表具有完整的读写权限。
使用 dba.configureInstance() 操作创建的 InnoDB Cluster 服务器配置帐户不会复制到 InnoDB Cluster 中的其他服务器。 MySQL Shell 自动禁用 dba.configureInstance() 指令所产生的 Binlog。这意味着您必须在每个服务器实例上单独创建 InnoDB Cluster 服务器配置帐户。
InnoDB Cluster管理员帐户
InnoDB Cluster管理员帐户可用于管理InnoDB Cluster。您可以设置多个集群管理员帐户,每个帐户必须存在于InnoDB Cluster中的每个成员服务器上,并具有相同的用户名和密码。
要为部署的 InnoDB ClusterSet 创建 InnoDB Cluster 管理员帐户,请在将所有实例添加到该集群后发出 cluster.setupAdminAccount() 命令。该命令将用您指定的用户名和密码创建一个帐户,并具授予所有必需的权限。使用 cluster.setupAdminAccount() 创建帐户所产生的事务将写入 Binlog 并发送到集群中的所有其他服务器实例以在其上创建帐户。
:::alert-info
【Note】
如果主 InnoDB Cluster 是在 MySQL Shell 8.0.20 之前的版本中设置的,则 cluster.setupAdminAccount() 命令可能已与 update 选项一起使用来更新 InnoDB Cluster 服务器配置帐户的权限。这是不写入 Binlog 的命令的特殊用途。
:::
MySQL Router账户
MySQL Router 使用这些帐户连接到 InnoDB Cluster 中的服务器实例。您可以设置多个,每个帐户必须存在于 InnoDB Cluster 中的每个成员服务器上,并具有相同的用户名和密码。创建 MySQL Router 帐户的过程与创建 InnoDB Cluster 管理员帐户的过程相同,但使用 cluster.setupRouterAccount() 命令。有关创建或升级 MySQL Router 帐户的说明,请参阅 第 6.10.2 节“配置 MySQL Router 用户 ”。
7.3.1. 手动配置 InnoDB Cluster 管理员帐户
如果要手动配置 InnoDB Cluster 管理用户,该用户需要此处列出的权限,且所有权限都带有 GRANT OPTION。
:::alert-info
【Note】
此权限列表基于 MySQL Shell 的当前版本。不同版本之间的权限可能会发生变化。因此,建议使用 dba.configureInstance() 或 cluster.setupAdminAccount() 设置 Cluster 管理员帐户。
:::
:::alert-info
【Important】
用于管理 InnoDB Cluster、InnoDB ClusterSet 或 InnoDB ReplicaSet 部署的每个帐户必须存在于部署中的所有成员服务器实例上,并且具有相同的用户名和密码。
:::
*.*上的RELOAD、SHUTDOWN、PROCESS、FILE、SELECT、SUPER、REPLICATION SLAVE、REPLICATION CLIENT、REPLICATION_APPLIER、CREATE USER、SYSTEM_VARIABLES_ADMIN、PERSIST_RO_VARIABLES_ADMIN、BACKUP_ADMIN、CLONE_ADMIN和EXECUTE全局权限。
:::alert-info
【Note】
SUPER 包括以下必需权限:SYSTEM_VARIABLES_ADMIN、SESSION_VARIABLES_ADMIN、REPLICATION_SLAVE_ADMIN、GROUP_REPLICATION_ADMIN、REPLICATION_SLAVE_ADMIN、ROLE_ADMIN。
:::
mysql_innodb_cluster_metadata.*、mysql_innodb_cluster_metadata_bkp.*和mysql_innodb_cluster_metadata_previous.*特定Schema的权限为ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EVENT, EXECUTE, INDEX, INSERT, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER, UPDATE;对于mysql.*Schema的权限为INSERT, UPDATE, DELETE。
如果只需要读取操作,例如创建用于监控目的的用户,则可以使用权限更受限制的帐户。为用户 your_user 授予监控 InnoDB Cluster 所需的权限:
GRANT SELECT ON mysql_innodb_cluster_metadata.* TO your_user@'%';
GRANT SELECT ON mysql.slave_master_info TO your_user@'%';
GRANT SELECT ON mysql.user TO your_user@'%';
GRANT SELECT ON performance_schema.global_status TO your_user@'%';
GRANT SELECT ON performance_schema.global_variables TO your_user@'%';
GRANT SELECT ON performance_schema.replication_applier_configuration TO your_user@'%';
GRANT SELECT ON performance_schema.replication_applier_status TO your_user@'%';
GRANT SELECT ON performance_schema.replication_applier_status_by_coordinator TO your_user@'%';
GRANT SELECT ON performance_schema.replication_applier_status_by_worker TO your_user@'%';
GRANT SELECT ON performance_schema.replication_connection_configuration TO your_user@'%';
GRANT SELECT ON performance_schema.replication_connection_status TO your_user@'%';
GRANT SELECT ON performance_schema.replication_group_member_stats TO your_user@'%';
GRANT SELECT ON performance_schema.replication_group_members TO your_user@'%';
GRANT SELECT ON performance_schema.threads TO your_user@'%' WITH GRANT OPTION;
欲了解更多信息,请参阅 账户管理语句。
7.3.2. InnoDB Cluster 创建的内部用户帐户
作为使用组复制的一部分,InnoDB Cluster 创建内部恢复用户,以启用 cluster 中服务器之间的连接。这些用户是集群内部的,生成的用户名遵循 mysql_innodb_cluster_server_id@% 的命名方案,其中 server_id 对于实例是唯一的。在 8.0.17 之前的版本中,生成的用户名遵循 mysql_innodb_cluster_r[10_numbers] 的命名方案。
这些内部用户使用的主机名设置为“%”。在 v8.0.17 之前,ipAllowlist 通过在 ipAllowlist 中为每个主机创建一个帐户来影响主机名行为。有关详细信息,请参阅 创建服务器白名单。
每个内部用户都有一个随机生成的密码。从版本8.0.18 开始,AdminAPI 允许您更改内部用户生成的密码。请参阅 重置恢复帐户密码。随机生成的用户将被授予以下权限:
GRANT REPLICATION SLAVE ON *.* to internal_user;
内部用户帐户在种子(seed)实例上创建,然后复制到集群中的其他实例。内部用户有:
-
通过执行
dba.createCluster()创建新集群时生成的用户 -
通过执行
Cluster.addInstance()将新实例添加到Cluster时生成的用户 -
Primary节点使用身份验证插件生成的用户
在 v8.0.17 之前,ipAllowlist 会使 Cluster.rejoinInstance() 删除旧的内部用户并生成新的用户,而不是重用它们。
有关组复制所需的内部用户的更多信息,请参阅 https://dev.mysql.com/doc/refman/8.0/en/group-replication-user-credentials.html。
7.3.3. 重置恢复帐户密码
从版本 8.0.18 开始,您可以使用 Cluster.resetRecoveryAccountsPassword() 重置 InnoDB Cluster 创建的内部恢复帐户的密码,例如遵循自定义密码生命周期策略。使用 Cluster.resetRecoveryAccountsPassword() 重置集群使用的所有内部恢复帐户的密码。该操作为每个在线实例上的内部恢复帐户设置一个新的随机密码。如果实例无法连接,则操作失败。您可以使用强制选项来忽略此类实例,但不建议这样做,并且在使用此操作之前将实例重新联机会更安全。此操作仅适用于用 InnoDB Cluster 创建的密码,不能用于更新手动创建的密码。
:::alert-info
【Note】
执行此操作的用户必须具有所有必需的管理权限,特别是 CREATE USER,以确保无论密码验证所需的策略如何,都可以更改恢复帐户的密码。换句话说,与 password_require_current 系统变量是否启用无关。
:::
7.4. 部署生产 InnoDB Cluster
在生产环境中部署时,组成 InnoDB Cluster 的 MySQL 服务器实例将在多台主机上运行,而不是在单台机器上运行,如 AdminAPI MySQL 沙箱 中所述。在继续执行这些说明之前,您必须将所需的软件安装到要作为服务器实例添加到InnoDB Cluster 的每台服务器上,请参阅 安装 MySQL AdminAPI 组件。
下图说明了您在本节中使用的场景:

:::alert-info
【Note】
与沙盒(sandbox)部署不同,沙盒部署中所有实例都本地部署到 AdminAPI 具有访问权限并可以保留配置更改的一台计算机中,而对于生产部署,您必须保留实例上的所有配置更改。如何执行此操作取决于实例上运行的 MySQL 版本,请参阅 持久化设置。
:::
要将服务器的连接信息传递给 AdminAPI,请使用类似 URI 的连接字符串或数据字典;请参阅 使用类似 URI 的字符串或键值对连接到服务器。在本文档中,显示了类似 URI 的字符串。
本节假设您拥有:
7.4.1. 预检查 InnoDB Cluster 将使用的实例配置
在创建生产部署之前,您需要检查每个 MySQL 实例是否配置正确。dba.configureInstance() 会检查实例并配置实例。您还可以选择使用 dba.checkInstanceConfiguration(instance) 函数检查实例是否满足 InnoDB Cluster 要求 中列出的要求,而无需更改实例上的任何配置。这不会检查实例上的任何数据,请参阅 检查实例状态以了解更多信息。
用于连接到实例的用户必须具有适当的权限,例如在 手动配置 InnoDB 集群管理员帐户 中配置的权限。下面演示了在运行的 MySQL Shell 中发出此命令:
mysql-js> dba.checkInstanceConfiguration('icadmin@ic-1:3306')
Please provide the password for 'icadmin@ic-1:3306': ***
Validating MySQL instance at ic-1:3306 for use in an InnoDB cluster...
This instance reports its own address as ic-1
Clients and other cluster members will communicate with it through this address by default.
If this is not correct, the report_host MySQL system variable should be changed.
Checking whether existing tables comply with Group Replication requirements...
No incompatible tables detected
Checking instance configuration...
Some configuration options need to be fixed:
+--------------------------+---------------+----------------+--------------------------------------------------+
| Variable | Current Value | Required Value | Note |
+--------------------------+---------------+----------------+--------------------------------------------------+
| enforce_gtid_consistency | OFF | ON | Update read-only variable and restart the server |
| gtid_mode | OFF | ON | Update read-only variable and restart the server |
| server_id | 1 | | Update read-only variable and restart the server |
+--------------------------+---------------+----------------+--------------------------------------------------+
Please use the dba.configureInstance() command to repair these issues.
{
"config_errors": [
{
"action": "restart",
"current": "OFF",
"option": "enforce_gtid_consistency",
"required": "ON"
},
{
"action": "restart",
"current": "OFF",
"option": "gtid_mode",
"required": "ON"
},
{
"action": "restart",
"current": "1",
"option": "server_id",
"required": ""
}
],
"status": "error"
}
对每个待加入 InnoDB Cluster 的实例重复此过程。运行 dba.checkInstanceConfiguration() 后生成的报告提供了有关在 InnoDB Cluster 部署中使用的实例所需的配置更改的信息。 config_error 部分中的 action 字段提示您该配置的修改是否需要重启实例才生效。
7.4.2. 配置实例以供 InnoDB Cluster 使用
AdminAPI 提供 dba.configureInstance() 函数,用于检查实例配置是否满足 InnoDB Cluster 使用,如果发现任何与 InnoDB Cluster 不兼容的设置,则修改实例配置。您对实例运行 dba.configureInstance() 命令,它会检查并配置用于 InnoDB Cluster 的设置项。如果实例不需要更改配置,则无需修改实例的配置项,并且 dba.configureInstance() 命令还会输出以确认该实例已准备好供 InnoDB Cluster 使用。
如果需要进行任何更改以使实例与 InnoDB Cluster 兼容,则会显示不兼容设置的报告,并且您可以选择让命令对实例的选项文件进行更改。根据 MySQL Shell 连接到实例的方式以及 MySQL 的版本,您可以通过将这些更改保存到远程实例的选项文件来使这些更改持久化,请参阅 持久化设置。
不支持持久化配置更改的实例自动要求您在本地配置实例,请参阅 使用 dba.configureLocalInstance() 配置实例 。或者,您可以手动更改实例的选项文件,请参阅 使用选项文件 了解更多信息。无论您以何种方式进行配置更改,您可能都必须重新启动 MySQL 以确保检测到配置更改。
dba.configureInstance() 命令的语法是:
dba.configureInstance([instance][, options])
其中 instance 是实例定义,options 是带有用于配置操作的附加选项的数据字典。该操作返回有关结果的描述性文本消息。
instance 是实例的连接数据。例如:
dba.configureInstance('user@192.168.3.211:3306')
有关更多信息,请参阅 使用类似 URI 的字符串或键值对连接到服务器。如果目标实例已经属于 InnoDB Cluster,则会生成错误并且该过程失败。
options 字典可以包含以下内容:
-
mycnfPath- 实例的MySQL选项文件的路径。请注意,InnoDB Cluster仅支持服务器实例的单个选项文件,并且不支持使用--defaults-extra-file选项来指定附加选项文件。对于使用实例选项文件的任何AdminAPI操作,必须指定主文件。 -
outputMycnfPath- 用于写入实例的MySQL选项文件的替代输出路径。 -
password- 连接使用的密码。 -
clusterAdmin- 要创建的InnoDB Cluster管理员用户的名称。支持的格式是标准MySQL帐户名格式。支持用户名和主机名的标识符或字符串。默认情况下,如果不加引号,则假定输入是字符串。请参阅 为 AdminAPI 创建用户帐户。 -
clusterAdminPassword- 使用clusterAdmin创建的InnoDB Cluster管理员帐户的密码。尽管您可以使用此选项进行指定,但这存在潜在的安全风险。如果您未指定此选项,但指定了clusterAdmin选项,系统会在交互式提示中提示您输入密码。 -
clearReadOnly- 用于确认super_read_only应设置为off的布尔值,请参阅 Super Read-only 的实例配置。此选项已弃用,并计划在未来版本中删除。 -
Interactive- 一个布尔值,用于在命令执行中禁用交互式向导,以便不向用户提供提示,也不显示确认提示。 -
restart- 一个布尔值,用于指示目标实例是否执行重启以完成操作。
尽管连接密码可以包含在实例定义中,但这是不安全的,不建议这样做。使用 MySQL Shell 可插入密码存储 来安全地存储实例密码。
一旦针对实例发出 dba.configureInstance() ,该命令就会检查该实例的设置是否适合 InnoDB Cluster 使用。将显示一个报告,其中显示 InnoDB Cluster 所需的设置。如果实例不需要对其设置进行任何更改,您可以在 InnoDB Cluster 中使用它,并可以继续 创建 InnoDB 集群。如果实例的设置对于 InnoDB Cluster 使用无效,则 dba.configureInstance() 命令会显示需要修改的设置。在配置实例之前,系统会提示您确认表中显示的更改,其中包含以下信息:
- Variable - 无效的配置变量。
- Current Value - 无效配置变量的当前值。
- Required Value - 配置变量所需的值。
如何继续操作取决于实例是否支持持久化设置,请参阅 持久化设置。当针对当前运行 MySQL Shell 的 MySQL 实例(即本地实例)发出 dba.configureInstance() 时,它会尝试自动配置该实例。当针对远程实例发出 dba.configureInstance() 时,如果该实例支持自动持久化配置更改,您可以选择执行此操作。如果远程实例不支持保存更改以将其配置为 InnoDB Cluster 使用,则必须在本地配置该实例。请参阅 使用 dba.configureLocalInstance() 配置实例。
一般来说,在 dba.configureInstance() 配置选项文件后不需要重新启动实例,但对于某些特定设置可能需要重新启动。此信息显示在发出 dba.configureInstance() 后生成的报告中。如果实例支持 RESTART 语句,MySQL Shell 可以关闭然后启动实例。这可确保 mysqld 检测到对实例选项文件所做的更改。有关详细信息,请参阅 https://dev.mysql.com/doc/refman/8.0/en/restart.html。
:::alert-info
【Note】
执行 RESTART 语句后,当前与实例的连接将丢失。如果启用自动重新连接,则服务器重新启动后将重新建立连接。否则,必须手动重新建立连接。
:::
dba.configureInstance() 方法验证是否有合适的用户可供集群使用,该用户用于集群成员之间的连接,请参阅 为 AdminAPI 创建用户帐户。
如果您不指定用户来管理集群,则在交互模式下,向导允许您选择以下选项之一:
- 为
root用户启用远程连接,不建议在生产环境中使用 - 创建一个新用户
- 没有自动配置,这种情况下需要手动创建用户
:::alert-info
【Tips】
如果实例的 super_read_only=ON,那么您可能需要确认 AdminAPI 可以设置 super_read_only=OFF。更多信息请参见 Super Read-only 的实例配置。
:::
7.4.2.1. dba.configureLocalInstance() 配置实例
不支持自动持久化配置更改的实例(请参阅 持久化设置)要求您连接到服务器、运行 MySQL Shell、本地连接到实例并发出 dba.configureLocalInstance()。这使得 MySQL Shell 能够在对远程实例运行以下命令后修改实例的选项文件:
dba.configureInstance()dba.createCluster()Cluster.addInstance()Cluster.removeInstance()Cluster.rejoinInstance()
:::alert-info
【Important】
未能将配置更改持久化到实例的选项文件可能会导致实例在下次重新启动后无法重新加入集群。
实例的相关配置选项,特别是组复制配置选项,必须位于单个选项文件中。 InnoDB Cluster 仅支持服务器实例的单个选项文件,不支持使用 --defaults-extra-file 选项指定附加选项文件。对于使用实例选项文件的任何 AdminAPI 操作,必须指定主文件。
:::
持久化配置更改的推荐方法是登录到远程计算机(例如使用 SSH),以 root 用户身份运行 MySQL Shell,然后连接到其本地 MySQL 服务器,如使用 --uri 选项连接到本地实例:
$> sudo -i mysqlsh --uri=instance
或者使用 \connect 命令登录到本地实例。然后发出 dba.configureInstance(instance),其中 instance 是本地实例的连接信息,以保留对本地实例的选项文件所做的任何更改。
mysql-js> dba.configureLocalInstance('user@192.168.3.212:3306')
对集群中不支持自动持久化配置更改的每个实例重复此过程。例如,如果您向集群添加 2 个不支持自动持久化配置更改的实例,则必须在实例重新启动之前连接到每台服务器并持久化 InnoDB Cluster 所需的配置更改。同样,如果您修改集群结构,例如更改实例数量,则需要对每个服务器实例重复此过程,以相应地更新集群中每个实例的InnoDB Cluster 元数据。
7.4.2.2. Super Read-only Mode 的实例配置
每当组复制停止时,super_read_only 变量就会设置为 ON 以确保不会对实例进行写入。当您尝试通过以下 AdminAPI 命令使用此类实例时,您可以选择在实例上设置 super_read_only=OFF:
dba.configureInstance()dba.configureLocalInstance()dba.dropMetadataSchema()
当 AdminAPI 遇到 super_read_only=ON 的实例时,在交互模式下,您可以选择设置 super_read_only=OFF。例如:
mysql-js> var myCluster = dba.dropMetadataSchema()
Are you sure you want to remove the Metadata? [y/N]: y
The MySQL instance at 'localhost:3310' currently has the super_read_only system
variable set to protect it from inadvertent updates from applications. You must
first unset it to be able to perform any changes to this instance.
For more information see:
https://dev.mysql.com/doc/refman/en/server-system-variables.html#sysvar_super_read_only.
Do you want to disable super_read_only and continue? [y/N]: y
Metadata Schema successfully removed.
实例的当前活动会话数将被显示。您必须确保任何应用程序都不会无意中写入实例。通过回答 y,您确认 AdminAPI 可以写入实例。如果列出的实例有多个打开的会话,请在允许 AdminAPI 设置 super_read_only=OFF 之前务必谨慎。
7.4.3. 创建 InnoDB Cluster
准备好实例后,使用 dba.createCluster() 函数创建集群,并使用 MySQL Shell 连接到的实例作为集群的种子(seed)实例。种子实例将被复制到您添加到集群中的其他实例,使它们成为种子实例的副本。如示例中,将ic-1 实例用作种子。当您发出 dba.createCluster(name) 时,MySQL Shell 会为连接到 MySQL Shell 当前全局会话的服务器实例创建一个经典 MySQL 协议会话。例如,要创建一个名为 testCluster 的集群,并将返回的集群分配给名为 cluster 的变量:
mysql-js> var cluster = dba.createCluster('testCluster')
Validating instance at icadmin@ic-1:3306...
This instance reports its own address as ic-1
Instance configuration is suitable.
Creating InnoDB cluster 'testCluster' on 'icadmin@ic-1:3306'...
Adding Seed Instance...
Cluster successfully created. Use Cluster.addInstance() to add MySQL instances.
At least 3 instances are needed for the cluster to be able to withstand up to
one server failure.
这种将返回的集群分配给变量的模式使您能够使用 Cluster 对象的方法对集群执行进一步的操作。返回的 Cluster 对象使用一个独立于 MySQL Shell 的全局会话的新会话。这确保了如果您更改 MySQL Shell 全局会话,Cluster 对象仍保持其与集群实例的会话连接。
为了能够管理集群,您必须确保拥有具有所需权限的合适用户。推荐的方法是创建管理用户。如果您在配置实例时未创建管理用户,请使用 Cluster.setupAdminAccount() 操作。例如,要创建一个名为 icadmin 的用户来管理分配给变量集群的 InnoDB Cluster,请发出:
mysql-js> cluster.setupAdminAccount("icadmin")
有关 InnoDB Cluster 管理员帐户的更多信息,请参阅 手动配置 InnoDB Cluster 管理员帐户。
dba.createCluster() 操作支持 MySQL Shell 的交互选项。当交互开启时,在以下情况下会出现提示:
- 如果实例属于组复制组,并且未将
FromGr: true设置为option,系统会询问您是否要采用该复制组。 - 如果未将
force: true设置为option,系统会要求您确认多主集群的创建。
当您运行 dba.createCluster() 以及通过运行 Cluster.addInstance() 将另一个服务器实例添加到 InnoDB Cluster 时,以下错误将记录到 MySQL 服务器实例的错误日志中。这些消息是无害的,与 AdminAPI 启动组复制的方式相关:
2020-02-10T10:53:43.727246Z 12 [ERROR] [MY-011685] [Repl] Plugin group_replication reported: 'The group name option is mandatory' 2020-02-10T10:53:43.727292Z 12 [ERROR] [MY-011660] [Repl] Plugin group_replication reported: 'Unable to start Group Replication on boot'
:::alert-info
【Note】
如果您遇到与元数据无法访问相关的错误,您可能配置了环回(loopback)网络接口。为了正确使用 InnoDB Cluster,请禁用环回接口。
:::
要检查集群是否已创建,请使用集群实例的 status() 函数。请参阅 使用 Cluster.status() 检查集群的状态。
:::alert-info
【Tip】
一旦服务器实例属于集群,仅使用 MySQL Shell 和 AdminAPI 来管理它们非常重要。不支持在将实例添加到集群后尝试手动更改实例上的组复制配置。同样,不支持在使用 AdminAPI 配置实例后修改对 InnoDB Cluster 至关重要的服务器变量,例如 server_uuid。
:::
使用 MySQL Shell 8.0.14 及更高版本创建集群时,您可以设置实例被驱逐出集群之前的等待时间(例如,当实例变得无法访问时)。将 expelTimeout 选项传递给 dba.createCluster(),该操作在种子(seed)实例上配置 group_replication_member_expel_timeout 变量。 expelTimeout 选项可以采用 0-3600 范围内的整数值。添加到配置了 expelTimeout 的集群的所有运行 MySQL 8.0.13 及更高版本的实例都会自动配置为具有与种子实例上配置的相同的 expelTimeout 值。
有关可以传递给 dba.createCluster() 的其他选项的信息,请参阅 修改或解散 InnoDB 集群。
从 MySQL Shell 8.0.33 开始,可以使用 dba.createCluster() 启用或禁用 group_replication_paxos_single_leader。
:::alert-info
【Note】
这只能由 MySQL Server 8.0.31 或更高版本上的 MySQL Shell 设置,因为 MySQL Shell 需要 replication_group_communication_information 表中的 WRITE_CONSENSUS_SINGLE_LEADER_CAPABLE 提供的信息,该信息是在 MySQL 8.0.31 中引入的。
:::
7.4.3.1. InnoDB Cluster 复制白名单
当您使用 MySQL Shell 8.0.28 及更高版本创建集群时,如果您有安全要求,即 AdminAPI 自动创建的所有帐户都具有严格的身份验证要求,则可以为 replicationAllowedHost 集群配置选项设置一个值。replicationAllowedHost 选项意味着自动创建的所有帐户只能从允许的主机进行连接,并使用严格的基于子网的过滤。以前,默认情况下,可以从任何地方访问 InnoDB Cluster 创建的内部用户帐户。
replicationAllowedHost 选项可以采用字符串值。例如,要创建名为 testCluster 的集群并将 replicationAllowedHost 选项设置为 192.0.2.0/24,请发出:
mysql-js> dba.createCluster('testCluster', {replicationAllowedHost:'192.168.3.0/24'})
7.4.3.2. 配置通信堆栈
从 MySQL Shell 8.0.30 开始,InnoDB Cluster 支持为 MySQL 8.0.27 中的组复制引入的 MySQL 通信协议堆栈。
选项 communicationsStack: XCOM|MYSQL 用于设置组复制的系统变量 group_replication_communication_stack 的值。如:
mysql-js> dba.createCluster("testCluster", {communicationStack: "xcom"})
MYSQL 通信堆栈是为 MySQL 8.0.27 或更高版本创建的所有新集群的默认设置。有关更多信息,请参阅 配置组复制通信堆栈。
7.4.4. 添加实例到 InnoDB Cluster
InnoDB Cluster 中至少需要 3 个实例才能容忍 1 个实例的故障。添加更多实例可以提高 InnoDB Cluster 对故障的容忍度。
从版本 8.0.17 开始,组复制实现了考虑实例补丁版本的兼容性策略,Cluster.addInstance() 操作会检测到这一点,如果出现不兼容性,操作将终止并报错。请参阅 检查 MySQL 实例版本 以及 将不同版本的成员合并到一个组中。
如果实例已包含数据,请先使用 cluster.checkInstanceState() 函数验证现有数据不会阻止实例加入集群。请参阅 检查实例状态。
使用 Cluster.addInstance(instance) 函数将实例添加到集群,其中 instance 是已配置实例的连接信息,请参阅 配置实例以供 InnoDB Cluster 使用。例如:
mysql-js> cluster.addInstance('icadmin@ic-2:3306')
A new instance will be added to the InnoDB cluster. Depending on the amount of
data on the cluster this might take from a few seconds to several hours.
Please provide the password for 'icadmin@ic-2:3306': ********
Adding instance to the cluster ...
Validating instance at ic-2:3306...
This instance reports its own address as ic-2
Instance configuration is suitable.
The instance 'icadmin@ic-2:3306' was successfully added to the cluster.
addInstance(instance[, options]) 函数的 options 字典提供以下属性:
- label:正在添加的实例的标识符。
- recoveryMethod:状态恢复的首选方法。可以是
auto(默认),clone, 或incremental。 - waitRecovery:整数值,指示命令是否应等待恢复过程完成及其详细级别。
- password:实例连接密码。
- memberSslMode:实例上使用的 SSL 模式。
- ipAllowlist:允许连接到实例进行组复制的主机列表,即白名单。
- localAddress:字符串值,其中包含要使用的组复制本地地址,而不是自动生成的地址。
- Interactive:布尔值,用于禁用/启用命令执行中的交互式向导,即根据设置的值是否提供提示和确认。默认值为
MySQL Shell向导模式。 - exitStateAction:指示组复制退出状态操作的字符串值。
- memberWeight:具有百分比权重的整数值,用于故障转移时自动主选举。
- autoRejoinTries:整数值,用于定义实例在被驱逐后尝试重新加入集群的次数。
将新实例添加到集群时,该实例的本地地址会自动添加到所有在线集群实例上的 group_replication_group_seeds 变量中,以便允许它们在需要时使用新实例重新加入组。
:::alert-info
【Note】
group_replication_group_seeds 中列出的实例按照它们在列表中出现的顺序使用。这可确保首先使用且优先使用用户指定的设置。有关更多信息,请参阅 定制 InnoDB Cluster 成员服务器”。
:::
如果您使用 MySQL 8.0.17 或更高版本,您可以选择实例如何与集群同步数据。只有当加入的实例恢复了集群之前处理的所有事务时,它才能作为在线实例加入并开始处理事务。有关更多信息,请参阅 结合使用 MySQL Clone 与 InnoDB Cluster
。
此外,在 8.0.17 及更高版本中,您可以配置 Cluster.addInstance() 的行为方式,让恢复操作在后台进行或在 MySQL Shell 中监视不同阶段的进度。
根据您选择从集群恢复实例的选项,您会在 MySQL Shell 中看到不同的输出。假设您要将实例 ic-2 添加到集群,而 ic-1 是种子(seed)或捐赠者(Donor)。
- 当您使用
MySQL Clone从集群恢复实例时,输出如下所示:
Validating instance at ic-2:3306... This instance reports its own address as ic-2:3306 Instance configuration is suitable. A new instance will be added to the InnoDB cluster. Depending on the amount of data on the cluster this might take from a few seconds to several hours. Adding instance to the cluster... Monitoring recovery process of the new cluster member. Press ^C to stop monitoring and let it continue in background. Clone based state recovery is now in progress. NOTE: A server restart is expected to happen as part of the clone process. If the server does not support the RESTART command or does not come back after a while, you may need to manually start it back. * Waiting for clone to finish... NOTE: ic-2:3306 is being cloned from ic-1:3306 ** Stage DROP DATA: Completed ** Clone Transfer FILE COPY ############################################################ 100% Completed PAGE COPY ############################################################ 100% Completed REDO COPY ############################################################ 100% Completed NOTE: ic-2:3306 is shutting down... * Waiting for server restart... ready * ic-2:3306 has restarted, waiting for clone to finish... ** Stage RESTART: Completed * Clone process has finished: 2.18 GB transferred in 7 sec (311.26 MB/s) State recovery already finished for 'ic-2:3306' The instance 'ic-2:3306' was successfully added to the cluster.
应遵守有关服务器重新启动的警告,您可能必须手动重新启动实例。请参阅 RESTART 语句。
- 当您使用增量恢复从集群中恢复实例时,输出如下所示:
Incremental distributed state recovery is now in progress. * Waiting for incremental recovery to finish... NOTE: 'ic-2:3306' is being recovered from 'ic-1:3306' * Distributed recovery has finished
要取消恢复阶段的监视,请发出 CONTROL+C。这会停止监视,但恢复过程会在后台继续进行。 waitRecovery 整数选项可与 Cluster.addInstance() 操作一起使用,以控制与恢复阶段有关的命令的行为。接受以下值:
- 0:不等待,让恢复过程在后台完成;
- 1:等待恢复过程完成;
- 2:等待恢复过程完成;并显示详细的静态进度信息;
- 3:等待恢复过程完成;并显示详细的动态进度信息(进度条);
默认情况下,如果运行MySQL Shell 的标准输出引用终端,则 waitRecovery 选项默认为 3。否则,默认为 2。请参阅 监控恢复操作
。
要验证实例是否已添加,请使用集群实例的 status() 函数。如下,是沙箱集群添加第二个实例后的状态输出:
mysql-js> cluster.status()
{
"clusterName": "testCluster",
"defaultReplicaSet": {
"name": "default",
"primary": "ic-1:3306",
"ssl": "REQUIRED",
"status": "OK_NO_TOLERANCE",
"statusText": "Cluster is NOT tolerant to any failures.",
"topology": {
"ic-1:3306": {
"address": "ic-1:3306",
"mode": "R/W",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
},
"ic-2:3306": {
"address": "ic-2:3306",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
}
}
},
"groupInformationSourceMember": "mysql://icadmin@ic-1:3306"
}
如何继续取决于实例对于运行 MySQL Shell 的实例是本地实例还是远程实例,以及实例是否支持自动持久化配置更改,请参阅 持久化设置。如果实例支持自动持久化保存配置更改,则您无需手动保存设置,可以添加更多实例或继续下一步。如果实例不支持自动持久化保存配置更改,您必须在本地配置实例。请参阅使用 dba.configureLocalInstance() 配置实例。这对于确保实例在离开集群后可重新加入集群至关重要。
:::alert-info
【Tip】
如果实例的 super_read_only=ON,那么您可能需要确认 AdminAPI 可以设置 super_read_only=OFF。更多信息请参见 Super Read-only Mode 实例配置。
:::
部署集群后,您可以配置 MySQL Router 以提供高可用性,请参阅 结合 AdminAPI、InnoDB Cluster 和 InnoDB ReplicaSet 使用 MySQL Router。
7.4.4.1. 检查实例状态
cluster.checkInstanceState() 函数可用于验证实例上的现有数据是否会阻止其加入集群。此过程的工作原理是与集群已处理的 GTID 进行比较,验证实例的全局事务标识符 (GTID) 状态。有关 GTID 的更多信息,请参阅 GTID 格式和存储。通过此检查,您可以确定是否可以将已处理事务的实例添加到集群中。
下面演示了在运行的 MySQL Shell 中发出此命令:
mysql-js> cluster.checkInstanceState('icadmin@ic-4:3306')
该函数的输出可以是以下之一:
- OK new:实例没有执行任何
GTID事务,因此与集群已执行的GTID不冲突 - OK recoverable:实例已执行的
GTID与集群种子(seed)实例已执行的GTID不冲突 - ERROR diverged:该实例已执行的
GTID与集群种子(seed)实例已执行的GTID不一致 - ERROR lost_transactions:该实例已执行的
GTID多于集群种子(seed)实例已执行的GTID
状态为 OK 的实例可以添加到集群中,因为该实例上的任何数据都与集群一致。换句话说,被检查的实例没有执行任何与集群已执行的 GTID 冲突的事务,并且可以恢复到与其余集群实例相同的状态。
7.4.5. 配置 InnoDB Cluster 端口
InnoDB Cluster 中的实例使用不同的端口进行不同类型的通信。如果您使用 XCOM 通信堆栈,除了默认端口 3306(用于接收 MySQL 协议的客户端连接)和 mysqlx_port(默认端口 33060 用于 X 协议的客户端连接)之外,还有一个用于集群中实例之间的内部连接的端口,不用于客户端连接。该端口由 localAddress 选项(对应系统变量 group_replication_local_address)配置,并且需要防火墙放行该端口,集群中的实例才能相互通信。例如,如果您的防火墙阻止此端口,则 InnoDB Cluster 中的实例无法相互通信,并且集群无法运行。同样,如果您的实例使用 SELinux,则需要确保 InnoDB Cluster 使用的所有必需端口均已打开,以便实例可以相互通信。请参阅 设置 MySQL 功能和 MySQL Shell 端口的 TCP 端口上下文 。
当您创建集群或向集群添加实例时,默认情况下,localAddress 端口的计算方法是:目标实例端口值 × 10 + 1。例如,当目标实例端口为 3306 时, localAddress 端口为 33061。您应确保集群实例使用的端口号与 localAddress 的计算方式兼容。例如,如果用于创建集群的服务器实例的 port 高于 6554,则 dba.createCluster() 操作会失败,因为计算出的 localAddress 端口号(65541)超出了最大有效端口(65535)。要避免这种情况,请为 InnoDB Cluster 的实例指定较低的 port 值,或手动分配 localAddress 值,例如:
mysql-js> dba.createCluster('testCluster', {'localAddress':'icadmin@ic-1:33061'}
如果您使用 MYSQL 通信堆栈,则 localAddress 值将使用与 MySQL 服务器相同的网络地址自动生成。不需要额外的内部端口/地址。请参阅 配置组复制通信堆栈。
localAddress 可以手动定义,但使用的端口必须是 MySQL 正在侦听的端口,如 bind_address 所定义。
7.4.6. 结合使用 MySQL Clone 与 InnoDB Cluster
在 MySQL 8.0.17 中,InnoDB Cluster 集成了 MySQL Clone 插件来提供加入实例的自动配置。检索 InnoDB Cluster 中的数据以便新实例能够与 InnoDB Cluster 同步的过程称为 分布式恢复。当新实例需要恢复 InnoDB Cluster 中的事务时,我们区分捐赠者(提供数据的集群实例)和接收者(从捐赠者接收数据的实例)。在之前的版本中,组复制仅提供基于 Binlog 的异步复制来为新实例恢复其加入集群所需的数据。对于具有大量先前处理的事务的集群,新实例可能需要很长时间来恢复所有事务,然后才能加入集群。或者,已删除 Binlog 的集群(例如作为定期维护的一部分)可能会丢失恢复新实例所需的一些事务。在这种情况下,唯一的替代方案是使用 MySQL Enterprise Backup 等工具手动配置实例,如 结合组复制使用 MySQL Enterprise Backup 中所示。
MySQL Clone 为实例提供了另一种分布式恢复的方法。 MySQL Clone 不依赖异步复制来恢复事务,而是创建捐赠者实例上的数据快照,然后将快照传输到接收者(待加入集群的新节点),属于物理恢复。
:::alert-info
【Warning】
在克隆操作期间,接收器中的所有先前数据都会被破坏(被捐赠者数据覆盖)。然而,所有未存储在表中的 MySQL 设置都会被保留。
:::
待加入的新节点(接收方)在完成克隆操作后,如果 InnoDB Cluster 处理了新的事务。则新节点可通过异步复制从捐赠者恢复新的事务数据。这比完全使用异步复制恢复所有事务要高效得多,并且避免了因清除 GTID(如删除了 Binlog) 引起的任何问题,使您能够快速为 InnoDB Cluster 预配置新实例。有关详细信息,请参阅 克隆插件 和 用于分布式恢复的克隆。
与使用 MySQL Clone 相反,增量恢复是加入集群的实例仅使用异步复制从集群中恢复实例的过程。当 InnoDB Cluster 配置为使用 MySQL Clone 时,加入集群的实例将使用 MySQL Clone 或增量恢复来恢复集群的事务。默认情况下,集群会自动选择最合适的方法,但您可以配置此默认行为,例如 强制克隆,这会替换加入实例已处理的任何事务。当您在交互模式下使用 MySQL Shell 时,默认情况下,如果集群不确定是否可以继续恢复,它会提供交互提示。
此外,处于 RECOVERING 状态的成员的 Cluster.status() 输出包括恢复进度信息,使您能够轻松监控恢复操作,无论它们是使用 MySQL Clone 还是增量恢复。 InnoDB Cluster 在 Cluster.status() 的输出中提供了有关使用 MySQL Clone 的实例的附加信息。
7.4.6.1. 使用 MySQL Clone 的 Cluster
使用 MySQL Clone 的 InnoDB Cluster 提供以下附加行为。
7.4.6.1.1. dba.createCluster() 与 MySQL Clone
从版本 8.0.17 开始,默认情况下,当在可用 MySQL Clone 插件的实例上创建新集群时,会自动安装该插件并将集群配置为支持克隆。InnoDB Cluster 恢复帐户是使用所需的 BACKUP_ADMIN 权限创建的。
将 disableClone 布尔选项设置为 true 以禁用 InnoDB Cluster 的 MySQL Clone。在这种情况下,会为此配置添加一个元数据条目,并且如果安装了 MySQL Clone 插件,则会将其卸载。您可以在发出 dba.createCluster() 时或在集群运行时使用 Cluster.setOption() 随时设置 disableClone 选项。
7.4.6.1.2. Cluster.addInstance(instance) 与 MySQL Clone
如果新实例运行 MySQL 8.0.17 或更高版本,并且集群中至少有一个运行 MySQL 8.0.17 或更高版本的捐赠者(包含在 group_replication_group_seeds 列表中),则 MySQL Clone 可用于新实例。使用 MySQL Clone 的集群遵循将实例添加到 InnoDB Cluster
中记录的行为,并添加了如何从 InnoDB Cluster 传输恢复新实例所需数据的可选项。 Cluster.addInstance(instance) 的行为方式取决于以下因素:
- 是否支持
MySQL Clone。 - 能否进行增量恢复,取决于
Binlog的可用性。如,如果捐赠者实例具有所需的所有Binlog(即GTID_PURGED为空),则可以进行增量恢复。如果InnoDB Cluster中所有实例都没有所需的Binlog,则增量恢复不可用。 - 增量恢复是否合适。尽管增量恢复可用,但由于它可能与新实例上已有的数据发生冲突,因此会检查捐赠者和接收者上的
GTID集以确认增量恢复是否合适。以下是可能的比较结果:- New: 接收者有一个空的
GTID_EXECUTED GTID集 - Identical:接收者的
GTID集与捐赠者的GTID集相同 - Recoverable:接收方的
GTID集丢失了事务,但可以从捐赠方恢复这些事务 - Irrecoverable:捐赠者的
GTID集丢失了事务,可能已被清除。 - Diverged:捐赠者和接收者的
GTID集有分歧
- New: 接收者有一个空的
当比较结果确定为“Identical”或“Recoverable”时,认为增量恢复是合适的。当比较结果被确定为 Irrecoverable 或 Diverged 时,增量恢复被认为是不合适的。
对于被视为 New 的实例,不能认为增量恢复是合适的,因为无法确定 Binlog 是否已被清除,甚至无法确定 GTID_PURGED 和 GTID_EXECUTED 变量是否被重置。或者,服务器可能在启用 Binlog 和 GTID 之前已经处理了事务。因此在交互模式下,您必须对要使用增量恢复进行确认。
gtidSetIsComplete选项的状态。如果确定已创建了具有完整GTID集的InnoDB Cluster,而无需额外确认即可添加具有空GTID集的新实例,则应将Cluster级别的gtidSetIsComplete配置项设为true。
:::alert-info
【Warning】
将 gtidSetIsComplete 选项设置为 true,意味着新加入的服务器将被恢复,无论它们包含什么数据,请谨慎使用。如果您尝试添加已应用了事务的实例,将面临数据丢失的风险。
:::
当您发出 Cluster.addInstance() 时,这些因素的组合会影响实例加入 InnoDB Cluster 的方式。 recoveryMethod 选项默认为 auto,这意味着在 MySQL Shell 的交互模式下,InnoDB Cluster 会自动为新实例选择从集群恢复数据的最佳方式,并且提示会建议您如何继续。换句话说, InnoDB Cluster 将根据最佳方法和服务器支持的内容,来推荐使用 MySQL Clone或增量恢复。如果您不使用交互模式并且正在编写 MySQL Shell 脚本,则必须将 recoveryMethod 设置为您要使用的恢复类型,即 clone 或 incremental。本节解释了不同的可能场景。
当您在交互模式下使用 MySQL Shell 时,添加新实例的所有可能选项的主要提示是:
Please select a recovery method [C]lone/[I]ncremental recovery/[A]bort (default Clone):
根据所提到的因素,您可能无法获得所有这些选项。本节后面描述的情景将解释为您提供哪些选项。此提示提供的选项有
- Clone
选择此选项可将捐赠者克隆到您待添加到 InnoDB Cluster 的新实例,并删除新实例中已包含的事务。 MySQL Clone 插件会被自动安装。 InnoDB Cluster 恢复帐户是使用所需的 BACKUP_ADMIN 权限创建的。假设您要添加一个空实例(未处理任何事务)或包含您不想保留的事务,请选择 Clone 选项。然后,集群使用 MySQL Clone,用来自捐赠者集群成员的快照完全覆盖待加入的新实例。要默认使用此方法并禁用此提示,请设置 InnoDB Cluster 的选项 recoveryMethod=clone 。
- Incremental recovery
选择此选项可使用增量恢复将 InnoDB Cluster 处理的所有事务以异步复制方式恢复到待加入 InnoDB Cluster 新实例。如果您确定集群处理的所有更新都是在启用 GTID 的情况下完成的、没有清除的事务并且新实例包含与 InnoDB Cluster 或其子集相同的 GTID 集,则增量恢复是合适的。要默认使用此选项,请设置 InnoDB Cluster 的选项 recoveryMethod=incremental。
上述因素的组合会影响提示时可用的选项,如下所示:
:::alert-info
【Note】
如果已在 AdminAPI 外部手动更改了 group_replication_clone_threshold 系统变量,则 InnoDB Cluster 可能会决定使用克隆恢复,而不是遵循这些场景。
:::
-
场景1:您可以在任何选项之间进行选择。建议您使用默认的
MySQL Clone。- 增量恢复是可能的
- 增量恢复不适合
- 支持克隆
-
场景2:系统不会向您提供提示,并且会使用增量恢复。
- 增量恢复是可能的
- 增量恢复是适合的
-
场景3:您无法使用
MySQL Clone将实例添加到集群。系统会向您提供提示,建议的选项是继续进行增量恢复。- 增量恢复是可能的
- 增量恢复不适合
- 不支持或禁用克隆
-
场景4:您无法将实例添加到
InnoDB Cluster并报错:必须克隆或完全配置目标实例,然后才能将其添加到目标集群。Cluster.addInstance显示需要实例配置(运行时错误),可能是从InnoDB Cluster所有实例中清除Binlog的结果。建议通过升级集群或设置disableClone=false来使用MySQL Clone。- 增量恢复是不可能的
- 不支持或禁用克隆
-
场景5:您只能使用
MySQL Clone将实例添加到InnoDB Cluster。这可能是由于InnoDB Cluster丢失Binlog造成的,例如当它们被清除时。- 增量恢复是不可能的
- 支持克隆
从提示中选择一个选项后,默认情况下会显示新实例从 InnoDB Cluster 恢复事务的进度。通过此监控,您可以检查恢复阶段是否正常运行,以及新实例加入 InnoDB Cluster 并 ONLINE 所需的时间。要取消恢复阶段的监视,请执行 CONTROL+C,事务恢复将于后台继续运行。
7.4.6.1.3. Cluster.checkInstanceState() 与 MySQL Clone
当运行 Cluster.checkInstanceState() 以针对使用 MySQL Clone 的 InnoDB Cluster 验证新实例时,如果新实例没有 Binlog,如 Binlog 已被清除但克隆可用且 disableClone=false 该操作提供了可以使用 Clone 的警告。例如:
The cluster transactions cannot be recovered on the instance, however, Clone is available and can be used when adding it to a cluster. { "reason": "all_purged", "state": "warning" }
同样,在 Clone 不可用或被禁用且 Binlog 不可用(如被清除)的实例上,输出包括:
The cluster transactions cannot be recovered on the instance. { "reason": "all_purged", "state": "warning" }
7.4.6.1.4. dba.checkInstanceConfiguration() and MySQL Clone
当对具有可用 MySQL Clone 但已禁用的实例运行 dba.checkInstanceConfiguration() 操作时,会显示警告。
7.4.7. 通过组复制部署 InnoDB Cluster
如果您已部署了组复制并且想依据它来创建 InnoDB Cluster,请在执行 dba.createCluster() 函数时,为其指定 acappFromGR: true 选项。将创建与复制组工作模式(单主还是多主)相匹配的 InnoDB Cluster。
mysql-js> var cluster = dba.createCluster('prodCluster', {adoptFromGR: true});
A new InnoDB cluster will be created on instance 'root@gr-member-2:3306'.
Creating InnoDB cluster 'prodCluster' on 'root@gr-member-2:3306'...
Adding Seed Instance...
Cluster successfully created. Use cluster.addInstance() to add MySQL instances.
At least 3 instances are needed for the cluster to be able to withstand up to
one server failure.
:::alert-info
【Tip】
如果实例的 super_read_only=ON,那么您可能需要确认 AdminAPI 可以设置 super_read_only=OFF。更多信息请参见 Super Read-only Mode 实例配置。
:::
如果您未指定 acceptFromGR: true,并且目标服务器实例属于复制组,MySQL Shell 会提示您确认是否要采用该复制组。从 MySQL Shell 8.0.29 开始,如果指定 AcceptFromGR: false,则如果发现实例属于复制组,则操作将停止且不提示。
新建的 InnoDB Cluster 与组的工作模式相匹配。如果采用的组在单主模式下运行,则会创建一个单主 InnoDB Cluster。如果采用的组在多主模式下运行,则会创建多主 InnoDB Cluster。
:::alert-info
【Note】
无法在指定了 AcceptFromGR 选项的命令中,定义 InnoDB Cluster 使用的通信堆栈。通过组复制创建的 InnoDB Cluster,在执行 dba.createCluster 初始化集群时,必须使用与复制组一致的通信堆栈。如有必要,可以在创建 InnoDB Cluster 之后,用 rebootClusterFromCompleteOutage 更改通信堆栈。请参阅 配置组复制通信堆栈。
:::
7.5. 配置 InnoDB Cluster
本节介绍如何在 InnoDB Cluster 创建过程中以及创建之后使用 AdminAPI 对 InnoDB Cluster 进行更详细的配置。您可以使用此章节内容来修改创建 InnoDB Cluster 时 AdminAPI 默认应用的设置。
7.5.1. 设置 InnoDB Cluster 选项
-
您可以在
InnoDB Cluster所有成员实例在线时,检查和修改InnoDB Cluster的设置。要检查当前设置,请使用以下操作:Cluster.options(),列出InnoDB Cluster及其成员实例的配置选项。还可以指定布尔选项all以在输出中包含有关所有组复制的系统变量信息。
-
您可以在集群级别或在线的实例级别配置
InnoDB Cluster的选项。这避免了删除、重配置、再添加实例来更改InnoDB Cluster选项的麻烦。使用以下操作:Cluster.setOption(option, value)全局更改InnoDB Cluster所有实例的设置或集群的全局设置,如clusterName。Cluster.setInstanceOption(instance, option, value)更改InnoDB Cluster中特定实例的设置。
-
如下这些选项在
InnoDB Cluster级别(所有实例)和特定实例级别都可更改:autoRejoinTries:整数值,用于定义实例在被驱逐出集群后,尝试重新加入集群的次数。请参阅 配置实例的自动重新加入。exitStateAction:指示组复制退出状态action的字符串值。请参阅 配置实例的自动重新加入。memberWeight:具有百分比权重的整数值,用于故障转移时自动Primary节点选举。请参阅 配置选举过程。ipAllowList:以逗号分隔的IP地址列表或子网CIDR表示法。如:192.168.1.0/24,10.0.0.1。默认,该值设置为AUTOMATIC,将成员实例所属的子网自动设置为白名单。仅当通信堆栈设置为XCOM时才能设置此选项。tag:option:与集群关联的内置标签和用户定义标签。请参阅 标记元数据。
-
如下选项只能在集群级别更改:
clusterName:定义InnoDB Cluster名称的字符串值disableClone:用于指定InnoDB Cluster是否禁用MySQL Clone分布式恢复。请参阅 dba.createCluster() 与 MySQL Clone。replicationAllowedHost:用于定义基于子网的白名单,以便内部管理的复制帐户只能从白名单中的主机进行连接。请参阅 InnoDB Cluster 复制白名单。expelTimeout:整数值,用于定义在将集群成员逐出InnoDB Cluster之前应等待的时长(以秒为单位)。请参阅 创建 InnoDB Cluster。failoverConsistency:表示InnoDB Cluster提供的一致性保证的字符串值。请参阅 配置实例的自动重新加入。transactionSizeLimit:设置组复制系统变量group_replication_transaction_size_limit的正整数值。用于限制InnoDB Cluster可接受的最大事务大小(字节为单位)。超出此限制的事务将被回滚并不会被广播到集群中。添加到InnoDB Cluster的所有成员都应使用相同的值。
-
此选项仅可在实例级别更改:
label:实例的字符串标识符
7.5.2. 定制 InnoDB Cluster 成员服务器
当您创建 InnoDB Cluster 并向其中添加实例时,组名称和本地地址等值将由 AdminAPI 自动配置。建议大多数部署使用默认值,但高级用户可以通过为 dba.createCluster() 和 Cluster.addInstance() 命令指定以下选项来覆盖默认值:
groupName- 为dba.createCluster()指定groupName选项,以设置InnoDB Cluster复制组的名称。这会设置group_replication_group_name系统变量。该名称必须是有效的UUID,可通过select uuid();生成。localAddress- 为dba.createCluster()和cluster.addInstance()指定localAddress选项(格式为host:port),以设置实例group_replication_local_address系统变量的值。该地址用于InnoDB Cluster内部成员之间的通信。
有关详细信息,请参阅这些 AdminAPI 选项配置的系统变量的文档。
7.5.3. 配置选举过程
您可以为单主模式 InnoDB Cluster 配置如何选举新的 Primary 节点,如优先选择特定的实例为故障转移后新的 Primary 节点。创建 InnoDB Cluster 时,为 dba.createCluster() 和 Cluster.addInstance() 指定 memberWeight 选项。memberWeight 选项接受 0 到 100 之间的整数,此值是故障转移时自动选主的百分比权重。当某个实例的 memberWeight 值较高时,它更有可能被选为 Primary 实例。进行初选时,如果多个实例具有相同的 memberWeight 值,则根据实例的 server-UUID 按从小到大的顺序排序,越小的值拥有越高的优先级。
设置 memberWeight 相当于配置了实例的 group_replication_member_weight 系统变量,取值范围为 0-100。如果提供更高或更低的值,则会被自动调整。如果未提供值,将使用默认值 50 。有关详细信息,请参阅 单主模式。
如,创建 InnoDB Cluster,Primary 节点为 ic-1。若 ic-1 故障,则优选 ic-3 为新的 Primary。可执行如下包含 memberWeight 选项的指令:
shell.connect('icadmin@ic-1') dba.createCluster('cluster1', {memberWeight:35}) var mycluster = dba.getCluster() mycluster.addInstance('icadmin@ic-2', {memberWeight:25}) mycluster.addInstance('icadmin@ic-3', {memberWeight:50})
7.5.4. 配置故障转移一致性
组复制提供了在单主模式的 InnoDB Cluster 发生了 Primary 节点故障转移时,指定事务一致性保障的能力(请参阅 配置事务一致性保障)。您可以在创建 InnoDB Cluster 时为 dba.createCluster() 指定 consistency 选项(在 8.0.16 之前,用 failoverConsistency,现已废弃),来配置 InnoDB Cluster 的事务一致性保证级别。该操作将配置种子(seed)实例中的 group_replication_consistency 系统变量。此选项定义了在单主模式中选举新 Primary 节点时,使用的新防护(fencing)机制。防护机制会要求新选出的 Primary 节点按序将积压队列中所有的 GTID 事务集应用完毕之后,才可向客户端提供读写服务。这可确保客户端应用不会从新选出的Primary 节点中读取过时的数据。
仅当目标 MySQL ≥ 8.0.14 时才支持 consistency 选项,并且在向已配置了 consistency 选项的 InnoDB Cluster 添加新实例时,会自动为新实例配置与集群成员拥有相同的 group_replication_consistency 选项。该变量的默认值(默认 EVENTUAL)由 Group Replication 控制。将 consistency 选项更改为 BEFORE_ON_PRIMARY_FAILOVER 即可启用 fencing 机制。设置 consistency=0 可将系统变量 group_replication_consistency 设置为 EVENTUAL;设置 consistency=1 可将系统变量 group_replication_consistency 设置为 BEFORE_ON_PRIMARY_FAILOVER。
:::alert-info
【Note】
在多主模式的 InnoDB Cluster 上使用 consistency 选项没有任何效果,但允许使用。因为在使用 Cluster.switchToSinglePrimaryMode() 将 InnoDB Cluster 切换为单主模式后,consistency 选项即可生效。
:::
7.5.5. 配置实例自动重新加入
MySQL ≥ 8.0.16 的实例支持组复制自动重新加入功能,您可以配置实例被驱逐后自动重新加入 InnoDB Cluster。有关背景信息,请参阅 对故障检测和网络分区的响应。AdminAPI 提供 autoRejoinTries 选项来配置实例在被驱逐出 InnoDB Cluster 后重新加入集群的尝试次数。默认情况下,实例不会自动重新加入 InnoDB Cluster。您可以使用以下命令在集群级别或单个实例配置 autoRejoinTries 选项:
dba.createCluster('mycluster', {autoRejoinTries: 5} )Cluster.addInstance('root@127.0.0.1:4404', {'autoRejoinTries':4} )Cluster.setOption('autoRejoinTries',5)Cluster.setInstanceOption('root@127.0.0.1:4403','autoRejoinTries',5)
autoRejoinTries 取值 0-2016 之间的整数,默认值为 3。使用自动重新加入功能时,您的 InnoDB Cluster 对故障的容忍度更高,尤其是临时故障(如不可靠的网络)。但若仲裁已丢失,您不应期望成员自动重新加入集群,因为需要多数(majority)才能重新加入实例。
运行 MySQL ≥ 8.0.12 的实例具有 group_replication_exit_state_action 变量,您可以使用 AdminAPI exitStateAction 选项配置该变量。这将控制实例在意外离开 InnoDB Cluster 时执行的 action 行为。默认情况下,exitStateAction 为 READ_ONLY,这意味着意外离开 InnoDB Cluster 的实例将变为只读。如果 exitStateAction 设置为 OFFLINE_MODE(从 MySQL 8.0.18 开始提供),意外离开 InnoDB Cluster 的实例会变为只读并进入离线模式,在该模式下它们会断开现有客户端的连接并且不再接受新连接(具有管理员权限的客户端除外) 。如果 exitStateAction 设置为 ABORT_SERVER,那么在意外离开 InnoDB Cluster 的实例将关闭 MySQL,并且必须再次启动它才能重新加入集群。请注意,当您使用自动重新加入功能时,exitStateAction 选项配置的操作仅在所有重新加入集群的尝试都失败的情况下才会发生。
您有可能连接到一个实例并尝试使用 AdminAPI 配置它,但此时该实例可能会重新加入集群。每当您使用以下任何操作时都可能发生这种情况:
Cluster.status()dba.getCluster()Cluster.rejoinInstance()Cluster.addInstance()Cluster.removeInstance()Cluster.rescan()Cluster.checkInstanceState()
当实例自动重新加入集群时,这些操作可能会提供额外的信息。此外,当您使用 Cluster.removeInstance() 时,如果目标实例自动重新加入集群,则操作将中止,除非您传入 force:true。
MySQL localhost:4401 ssl JS > cluster.removeInstance( 'root@127.0.0.1:4404', {"force":true} )
7.5.6. 配置并行复制应用线程
从版本 8.0.23 开始,实例支持并启用并行复制应用程序线程,有时称为 多线程副本。并行使用多个副本应用程序线程可提高复制应用线程和增量恢复的吞吐量。
这意味着在运行 MySQL ≥ 8.0.23 的实例上,必须配置以下系统变量:
binlog_transaction_dependency_tracking=WRITESETslave_preserve_commit_order=ONslave_parallel_type=LOGICAL_CLOCKtransaction_write_set_extraction=XXHASH64
默认情况下,应用程序线程数(由 slave_parallel_workers 系统变量配置)设置为 4。
当您升级运行 MySQL < 8.0.23 的 MySQL 服务器和 MySQL Shell 的集群时,实例不会配置为使用并行复制应用线程。如果未启用并行应用线程,Cluster.status() 操作的输出会在 instanceErrors 字段中显示一条消息,例如:
... "instanceErrors": [ "NOTE: The required parallel-appliers settings are not enabled on the instance. Use dba.configureInstance() to fix it." ...
在此情况下,您应该重新配置实例,以便它们使用并行复制应用线程。对于属于InnoDB Cluster 的每个实例,通过发出 dba.configureInstance(instance) 更新配置。请注意,通常在将实例添加到 InnoDB Cluster 之前使用 dba.configureInstance(),但在这种特殊情况下,无需删除实例,并且配置更改是在实例在线时进行的。
有关并行复制应用线程的信息显示在 Cluster.status(extended=1) 操作的输出中。例如,如果启用并行复制应用线程,则实例的拓扑部分输出将显示 applierWorkerThreads 下的线程数。为并行复制应用线程配置的系统变量显示在 Cluster.options() 操作的输出中。
您可以使用 applierWorkerThreads 选项配置实例用于并行复制的应用线程数,默认为 4。该选项接受 0-1024 的整数,并且只能与 dba.configureInstance() 和 dba.configureReplicaSetInstance() 操作一起使用。例如,要使用 8 个线程,请发出:
mysql-js> dba.configureInstance( 'root@127.0.0.1:4404', {applierWorkerThreads: 8, restart: true} )
:::alert-info
【Note】
并行复制应用程序使用的线程数的更改仅在实例重新启动并重新加入集群后生效。
:::
要禁用并行复制应用线程,请将 applierWorkerThreads 选项设置为 0。
7.5.7. InnoDB Cluster 与自增
当您使用实例作为 InnoDB Cluster 的一部分时,auto_increment_increment 和 auto_increment_offset 变量配置可避免多主集群发生自增冲突的可能性,最大大小为 9(组复制组支持的最大大小) 。用于配置这些变量的逻辑可以概括为:
- 如果
InnoDB Cluster在单主模式下运行,则将auto_increment_increment设置为1,将auto_increment_offset设置为2。 - 如果
InnoDB Cluster在多主模式下运行,则当集群有≤7个实例时,将auto_increment_increment设置为7,将auto_increment_offset设置为1 + server_id % 7。如果集群≥8个实例,请将auto_increment_increment设置为实例数,将auto_increment_offset为1 + server_id % 实例数。
7.5.8. InnoDB Cluster 和 Binlog 清除
在 MySQL 8 中,Binlog 会自动清除(由 binlog_expire_logs_seconds 定义)。这意味着运行时间超过 binlog_expire_logs_seconds 的集群最终可能不具有完整 Binlog 的实例,该 Binlog 包含实例应用的所有事务。这可能会导致需要预先配置实例,例如使用 MySQL Enterprise Backup,然后才能加入集群。运行 MySQL ≥ 8.0.17 的实例支持 MySQL Clone 插件,该插件通过提供不依赖增量恢复的自动配置解决方案解决了此问题,请参阅结合使用 MySQL Clone 与 InnoDB Cluster。运行 MySQL < 8.0.17的实例仅支持增量恢复,结果是,根据实例运行的 MySQL 版本,可能必须预先配置实例。否则依赖分布式恢复的操作,例如 Cluster.addInstance() 等可能会失败。
在运行早期版本 MySQL 的实例上,以下规则用于 Binlog 清除:
MySQL < 8.0.1的实例默认没有Binlog自动清除功能,因为expire_logs_days默认值为0。- 运行
8.0.1 ≤ MySQL < 8.0.4的实例会在30天后清除Binlog,因为expire_logs_days默认值为30。 - 运行
MySQL > 8.0.10的实例会在30天后清除Binlog,因为binlog_expire_logs_seconds默认值为2592000,expire_logs_days默认值为0。
因此,根据 InnoDB Cluster 运行的时间长短,Binlog 可能已被清除,您可能需要手动配置实例。同样,如果您手动清除 Binlog,您可能会遇到相同的情况。因此,强烈建议您升级到 MySQL ≥ 8.0.17 的版本,以充分利用 MySQL Clone 提供的自动配置功能进行分布式恢复,并在为 InnoDB Cluster 配置实例时最大程度地减少停机时间。
7.5.9. 配置组复制通信堆栈
从 MySQL Shell 8.0.30 开始,InnoDB Cluster 和ClusterSet 支持在 MySQL 8.0.27 中为组复制引入的 MySQL 通信堆栈。
新选项 communicationsStack: XCOM|MYSQL 可用于设置组复制系统变量 group_replication_communication_stack 的值。
:::alert-info
【Note】
无法将 communicationStack 选项与 acceptfromGR 一起使用。使用 acceptfromGR 创建 InnoDB Cluster 时,将继承组复制中系统变量 group_replication_communication_stack 的值。
:::
7.5.9.1. 通信堆栈类型
支持以下通信堆栈:
-
MYSQL:(MySQL Server ≥ 8.0.27的默认值)- 通过使用
MySQL Server的连接安全性代替组复制实现来简化InnoDB Cluster的创建。 - 内部组复制通信不需要额外的网络地址或端口。
- 使用
MYSQL协议意味着可以使用标准的用户身份验证方法代替白名单来授予或撤销对组的访问权限。 - 支持组复制的网络命名空间。
Oracle建议使用MYSQL通信堆栈而不是XCOM。
- 通过使用
-
XCOM:(MySQL Server ≤ 8.0.26的默认设置)。您可以将XCOM通信堆栈与MySQL Server ≥ 8.0.27一起使用,但必须在创建或重新启动命令中显式定义。XCOM使用安全协议的组复制实现(包括TLS/SSL以及使用传入组通信系统 (GCS) 连接的白名单列表)来保护成员之间组通信的连接和分布式恢复的连接。
7.5.9.2. 选择通信堆栈
通信堆栈选择由 dba.createCluster() 和 <clusterSet>.createReplicaCluster() 命令中的 communicationsStack 选项指定。如:
js> dba.createCluster("testCluster", {communicationStack: "mysql"})
js> clusterset.createReplicaCluster("hostname:3306", "replica", {communicationStack: "mysql"})
每个命令都会检查 MySQL 服务器以确保它可以使用 MYSQL 协议。若不支持 MYSQL 协议,则会显示错误并且命令失败。
addInstance、rejoinInstance 和 rescan 命令还会检查目标实例是否支持通信栈,并相应设置所需的配置选项。
ipAllowListXCOM:默认情况下自动设置。MYSQL:清除设置的值。MYSQL通信堆栈不允许使用ipAllowList。
localAddressXCOM:(高级选项,不推荐)自动生成。需要额外的网络地址或端口。MYSQL:自动更新为使用MySQL服务器报告的值。localAddress可以手动定义,但端口必须是MySQL正在侦听的端口,如 bind_address 所定义。
groupSeedsXCOM:自动生成。需要额外的网络地址或端口。MYSQL:自动更新为使用每个MySQL实例使用的bind_address值。
- 更新 SSL 设置。两种通信协议使用相同的
SSL设置。如果设置memberSslMode为VERIFY_CA或VERIFY_IDENTITY,则从MySQL服务器复制设置。如果设置memberSslMode为REQUIRED,则不会进行任何更改。
:::alert-info
【Note】
如果 memberSslMode 设置为 DISABLED 以外的任何值,则 group_replication_recovery_use_ssl 将始终启用。
:::
7.5.9.3. 切换通信堆栈
可以在完全中断操作重新启动期间切换通信堆栈。如:
js> dba.rebootClusterFromCompleteOutage("testcluster", {switchCommunicationStack: "mysql"})
从 MYSQL 协议切换到 XCOM 需要 localAddress 的附加网络地址,并且可能还需要 ipAllowList 值。
如果从 XCOM 切换到 MYSQL 堆栈,则会进行以下更改:
ipAllowList清除(unset)ipAllowList的值localAddress已更新为使用 MySQL 服务器报告的值。groupSeeds已更新为使用每个MySQL实例使用的bind_address值。- 更新 SSL 设置。如果设置
memberSslMode为VERIFY_CA或VERIFY_IDENTITY,则从MySQL服务器复制设置。如果设置memberSslMode为REQUIRED,则不会进行任何更改。
:::alert-info
【Note】
如果 memberSslMode 设置为 DISABLED 以外的任何值,则 group_replication_recovery_use_ssl 将始终启用。
:::
7.6. 保护 InnoDB Cluster
服务器实例可以配置为使用安全连接。有关使用 MySQL 安全连接的一般信息,请参阅 使用加密连接。本节介绍如何配置 InnoDB Cluster 以使用加密连接。另一种安全可能性是配置哪些服务器可以访问集群,请参阅 创建服务器白名单。
:::alert-info
【Important】
如果您使用 XCOM 通信堆栈,一旦将集群配置为使用加密连接,您必须将服务器添加到 ipAllowlist。例如,使用商业版 MySQL 时,默认启用 SSL,您需要为所有实例配置 ipAllowlist 选项。请参阅 创建服务器白名单。
:::
使用 dba.createCluster() 设置集群时,如果服务器实例提供加密,则会在种子(seed)实例上自动启用加密。可在执行 dba.createCluster() 方法时,通过 memberSslMode 选项指定不同的 SSL 模式(mode)。集群的 SSL 模式只能在创建 InnoDB Cluster 时设置。 memberSslMode 选项默认为 AUTO。支持以下取值:
DISABLED:确保为集群中的种子实例禁用SSL加密。AUTO:如果服务器实例支持,则自动启用SSL加密;如果服务器不支持,则禁用加密。REQUIRED:为集群中的种子实例启用SSL加密。如果无法启用,则会引发错误。VERIFY_CA:与REQUIRED类似,但还根据配置的CA证书验证服务器的证书(CA) 。如果未找到有效的匹配CA证书,连接尝试将失败。VERIFY_IDENTITY:与VERIFY_CA类似,但还通过根据服务器发送给客户端的证书中的身份,检查客户端用于连接到服务器的主机名来执行主机名身份验证。
例如,执行如下指令,将集群的 SSL mode 设置为 REQUIRED:
mysql-js> var myCluster = dba.createCluster({memberSslMode: 'REQUIRED'})
如果您选择使用 VERIFY_CA 或 VERIFY_IDENTITY 模式,则必须在每个集群实例上使用 ssl_ca 和/或 ssl_capath 选项手动提供 CA 证书。有关这些模式的更多信息,请参阅 –ssl-mode=mode。
当您使用 Cluster.addInstance() 和 Cluster.rejoinInstance() 操作时,会根据 InnoDB Cluster 已使用的加密设置来启用或禁用实例上的 SSL 加密。在执行这些操作时,可通过 memberSslMode 选项为实例指定特定的加密模式。
当使用 dba.createCluster() 和 attendFromGR 选项依据现存的复制组创建 InnoDB Cluster 时,新建的 InnoDB Cluster 将继承复制组的 SSL 设置:
-
memberSslMode不能与AcceptFromGR一起使用。 -
若
attendFromGR选项所采用的复制组的SSL设置与MySQL Shell支持的SSL(即用于组复制恢复和组通信的 SSL)设置不同,则这两个设置都不会被修改。这意味着您无法向InnoDB Cluster添加新实例,除非您手动更改所采用的复制组的SSL设置。
MySQL Shell 始终为集群启用或禁用 SSL 以进行组复制中的数据恢复和组内成员的通信,请参阅 使用安全套接字层 (SSL) 保护组通信连接。将新实例添加到集群时,如果种子实例的这些设置不同(例如,使用采用FromGR 的 dba.createCluster() 的结果),则会执行验证并发出错误。必须为集群中的所有实例启用或禁用 SSL 加密。执行验证以确保在向集群添加新实例时此不变量成立。
默认情况下,dba.deploySandboxInstance() 命令将尝试部署支持 SSL 加密的沙箱实例。若无法部署,则尝试部署不支持 SSL 的沙箱实例。请参阅 部署 Sandbox 实例。
7.6.1. 确保集群成员之间的通信安全
https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-innodb-cluster-securing.html
从 MySQL Shell 8.0.33 开始,可以将集群和副本集群(replica clusters)配置为使用 SSL 加密复制通道,并使副本能通过 SSL 证书验证主机身份。
使用 dba.createCluster() 创建集群时,您可以使用 memberAuthType 选项定义 InnoDB Cluster 内部复制帐户所用的身份验证类型。该选项的取值范围如下:
PASSWORD:帐户仅使用密码进行身份验证。CERT_ISSUER:帐户使用客户端证书进行身份验证,该证书必须与预期的颁发者(issuer)匹配。该值相当于VERIFY_CA。CERT_SUBJECT:帐户使用客户端证书进行身份验证,该证书必须与预期的颁发者(issuer)和主题(subject)匹配。该值相当于VERIFY_IDENTITY。CERT_ISSUER_PASSWORD:帐户使用PASSWORD和CERT_ISSUER组合进行身份验证。CERT_SUBJECT_PASSWORD:帐户使用PASSWORD和CERT_SUBJECT组合进行身份验证。
:::alert-info
【Important】
ClusterSet 继承主集群上定义的 memberAuthType。 ClusterSet 中的所有副本集群(replica clusters)也将使用主集群上定义的 memberAuthType。
:::
SSL 证书使用以下选项定义:
- CERT_ISSUER:如果
memberAuthType包含CERT_ISSUER或CERT_SUBJECT,则定义拓扑中所有复制帐户所需的证书颁发者(issuer)。 - CERT_SUBJECT:定义实例的证书主题(
subject)。如果memberAuthType包含CERT_SUBJECT,则SSL证书中此选项为必需。
:::alert-info
【Note】
除了 password 之外,不能将 acceptFromGR=true 与任何 memberAuthType 一起使用。
:::
以下示例创建一个集群 cluster1,它将客户端 SSL 连接和由组复制打开的从一台服务器到另一台服务器的连接设置为 VERIFY_IDENTITY,并将内部复制帐户的身份验证设置为需要客户端证书:
cluster = dba.createCluster("cluster1", { "memberSslMode": "VERIFY_IDENTITY", "memberAuthType":"CERT_SUBJECT",
"certIssuer":"/CN=MyCertAuthority", "certSubject": "/CN=mysql-1.local"});
以下示例演示如何使用 "memberAuthType":"CERT_SUBJECT" 将实例添加到 InnoDB Cluster:
cluster.addInstance("mysql-2.local", {"certSubject": "/CN=mysql-2.local"});
有关复制和加密连接的详细信息,请参阅 设置复制以使用加密连接。
7.6.2. 创建服务器白名单
:::alert-info
【Note】
这仅适用于 XCOM 通信堆栈。
:::
使用 createCluster()、addInstance() 和 rejoinInstance() 方法,您可以选择指定已批准(approved)的服务器列表(称为白名单)。通过以这种方式显式指定白名单,可以提高 InnoDB Cluster 的安全性,因为只有白名单中的服务器才能连接到 InnoDB Cluster。
您还可以为正在运行的 InnoDB Cluster 定义 allowList,使用 Cluster.setOption() 为 InnoDB Cluster 的所有成员指定 allowList,并使用 Cluster.setInstanceOption() 为单个成员指定 allowList。请参阅 。
设置 InnoDB Cluster 选项
使用 ipAllowlist 选项(以前称为 ipWhitelist,现已弃用)在实例上配置 group_replication_ip_allowlist 系统变量。默认情况下,如果未明确指定,自动将服务器所在的子网设置为白名单。要配置白名单(allowlist),请在使用该方法时使用 ipAllowlist 选项指定要添加的服务器(IP 或主机名)。 IP 地址必须以 IPv4 格式指定。多个服务器地址用逗号分隔,并用引号括起。例如:
mysql-js> cluster.addInstance("icadmin@ic-3:3306", {ipAllowlist: "203.0.113.0/24, 198.51.100.110"})
这将实例配置为仅接受来自地址 203.0.113.0/24 和 198.51.100.110 的服务器的连接。白名单(allowlist)还可以设置为主机名,仅当另一台服务器发出连接请求时才会解析该主机名。
:::alert-danger
【Warning】
白名单(allowlist)中的主机名本质上不如 IP 地址安全。 MySQL 执行 FCrDNS 验证,这提供了良好的保护级别,但可能会受到某些类型的攻击的影响。仅当绝对必要时才在白名单(allowlist)中指定主机名,并确保用于名称解析的所有组件(如 DNS 服务器)均可控。您还可以使用主机文件在本地实现名称解析,以避免使用外部组件。
:::
7.7. 监控 InnoDB Cluster
本章节描述如何用 AdminAPI 监控 InnoDB Cluster。
7.7.1. 使用 Cluster.describe()
可使用 Cluster.describe() 函数,获取有关 InnoDB Cluster 自身结构的描述信息。如:
mysql-js> cluster.describe();
{
"clusterName": "testCluster",
"defaultReplicaSet": {
"name": "default",
"topology": [
{
"address": "ic-1:3306",
"label": "ic-1:3306",
"role": "HA"
},
{
"address": "ic-2:3306",
"label": "ic-2:3306",
"role": "HA"
},
{
"address": "ic-3:3306",
"label": "ic-3:3306",
"role": "HA"
}
]
}
}
该函数的输出显示了 InnoDB Cluster 的结构,包括其所有的配置信息等。address、label 和 role 与使用 Cluster.status() 检查集群状态所展示的值一致。
7.7.2. 使用 Cluster.status() 检查集群状态
Cluster 对象了提供 status() 方法,使您能够检查集群的运行情况。在检查 InnoDB Cluster 的状态之前,您需要通过连接到 InnoDB Cluster 的实例来获取对 InnoDB Cluster 对象的引用。但是,如果要更改集群的配置,则必须连接到 “R/W” 实例。发出 status() 会根据您所连接的服务器实例所了解的集群视图检索集群的状态,并输出状态报告。
:::alert-danger
【Important】
InnoDB Cluster 中实例的状态直接影响状态报告中提供的信息。因此,请确保您连接到的实例的状态为 “ONLINE”。
:::
可通过 status() 方法,了解有关 InnoDB Cluster 如何运行:
mysql-js> var cluster = dba.getCluster()
mysql-js> cluster.status()
{
"clusterName": "testcluster",
"defaultReplicaSet": {
"name": "default",
"primary": "ic-1:3306",
"ssl": "REQUIRED",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"ic-1:3306": {
"address": "ic-1:3306",
"memberRole": "PRIMARY",
"mode": "R/W",
"readReplicas": {},
"replicationLag": "applier_queue_applied",
"role": "HA",
"status": "ONLINE"
"version": "8.0.30"
},
"ic-2:3306": {
"address": "ic-2:3306",
"memberRole": "SECONDARY",
"mode": "R/O",
"readReplicas": {},
"replicationLag": "applier_queue_applied",
"role": "HA",
"status": "ONLINE"
"version": "8.0.30"
},
"ic-3:3306": {
"address": "ic-3:3306",
"memberRole": "SECONDARY",
"mode": "R/O",
"readReplicas": {},
"replicationLag": "applier_queue_applied",
"role": "HA",
"status": "ONLINE"
"version": "8.0.30"
}
}
"topologyMode": "Single-Primary"
},
"groupInformationSourceMember": "mysql://icadmin@ic-1:3306"
}
Cluster.status() 的输出提供以下信息:
clusterName:在执行dba.createCluster()时,分配给该InnoDB Cluster的名称。defaultReplicaSet:属于InnoDB Cluster并包含数据集的服务器实例。primary:仅当InnoDB Cluster运行于单主模式时显示此字段。显示当前主(primary)实例的地址。如果不显示该字段,则InnoDB Cluster运行于多主模式。ssl:InnoDB Cluster是否使用安全连接。显示REQUIRED还是DISABLED,取决于在执行createCluster()或addInstance()时,配置的memberSslMode选项。选项memberSslMode返回的值对应于实例上的group_replication_ssl_mode服务器变量的值。请参阅 保护 InnoDB Cluster。status:InnoDB Cluster的状态。该状态描述了该集群提供的高可用性。状态值为以下之一:OK:集群在线,最多可以容忍n次故障。集群中有3个及以上成员,并且它们正在运行。OK_PARTIAL:集群在线,最多可以容忍n次故障。集群中至少有3台成员服务器处于Group Replication的在线状态。但是,一台或多台成员服务器当前未作为InnoDB Cluster的活动(active)成员参与。OK_NO_TOLERANCE:InnoDB Cluster不能容忍任何故障。OK_NO_TOLERANCE_PARTIAL:InnoDB Cluster不能容忍任何故障。InnoDB Cluster中一台或两台成员服务器在线,但一台或多台服务器处于offline、recovering、error或unreachable状态 。由于某些成员不可用,InnoDB Cluster对故障的容忍度不够。NO_QUORUM:InnoDB Cluster没有仲裁,这意味着复制组的大多数成员服务器无法就决策达成一致,并且无法处理写入事务。OFFLINE:InnoDB Cluster内所有成员均离线。ERROR:InnoDB Cluster中没有在线成员。UNREACHABLE:没有与任何在线成员的连接。UNKNOWN:没有与任何在线成员的连接。FENCED_WRITES:InnoDB Cluster被隔离以防止产生数据写入。
topology:MySQL Server实例的状态。状态为以下之一:Host name of instance:实例的主机名,例如 “localhost:3310”。memberRole:组复制插件报告的成员角色,请参阅 replication_group_members 表的MEMBER_ROLE列。mode:服务器是读写(“R/W”)还是只读(“R/O”)。从版本8.0.17开始,这是根据实例上super_read_only变量的当前状态以及InnoDB Cluster是否具有法定人数(quorum)得出的。在以前的版本中,mode的值是根据实例是作为主(primary)实例还是辅助(secondary)实例而派生的。通常,如果实例是主实例,则模式为 “R/W”,如果实例是辅助实例,则模式为 “R/O”。InnoDB Cluster中任何没有可见仲裁的实例都被标记为 “R/O”,无论super_read_only变量为何值。如果成员状态不是 “ONLINE”,则模式将报告为 “n/a”。replicationLag:返回以下值之一:- 最后一个事务提交时间戳和最后一个事务应用时间戳之间的时间差,格式为
HH:MM:SS。如果使用多个Worker线程,则从执行最旧事务的Worker线程中检索该值。 null:复制连接或SQL线程未运行。applier_queue_applied:应用(applier)程序队列已应用所有内容。即如果最后排队的事务和最后应用的事务相同,或者正在应用的事务为0。
- 最后一个事务提交时间戳和最后一个事务应用时间戳之间的时间差,格式为
role:该实例在InnoDB Cluster中提供什么功能。目前只有HA,以实现高可用性。status:InnoDB Cluster中该元素的状态。状态为以下之一:ONLINE:实例在线并加入InnoDB Cluster。OFFLINE:该实例已失去与其他实例的连接。RECOVERING:实例正在尝试通过检索其成为在线成员之前所需的事务来与集群同步,即正在执行分布式恢复。UNREACHABLE:实例与InnoDB Cluster失去通信。ERROR:实例在恢复阶段或应用事务时遇到错误。一旦实例进入ERROR状态,super_read_only选项将被设置为ON。要离开ERROR状态,您必须手动将实例配置为super_read_only=OFF。(MISSING):实例已完成部分配置,但当前状态不可用。MISSING状态是InnoDB Cluster特有的,它不是由Group Replication生成的状态。MySQL Shell使用此状态来指示在元数据中注册,但在实时InnoDB Cluster视图中找不到的实例。
groupInformationSourceMember:用于获取有关InnoDB Cluster的信息的内部连接,显示为类似URI的连接字符串。通常是最初用于创建InnoDB Cluster的连接。
version:实例上运行的MySQL Server版本。有关更多信息,请参阅 检查 MySQL 实例版本。
要显示有关 InnoDB Cluster 的更多信息,请使用 extended 选项。从版本 8.0.17 开始,extended 选项支持整数或布尔值。要配置 Cluster.status({'extended':value}) 提供的附加信息,请使用以下值:
0:禁用附加信息,默认1:包括的信息有组复制协议版本、组名称、通信堆栈、集群成员的UUID、集群成员的角色和组复制报告的状态(state),以及受保护的系统变量列表。2:包括关于连接和应用线程处理的事务的信息3:包括有关InnoDB Cluster每个成员执行的复制的更详细的统计信息。
使用布尔值设置 extended 相当于设置整数值 0 和 1。在 8.0.17 之前的版本中,extended 选项仅为 布尔值。同样,之前的版本使用 queryMembers 布尔选项来提供有关 InnoDB Cluster 中实例的更多信息,这相当于将 extended 设置为 3。queryMembers 选项已弃用,并计划在未来版本中删除。
当执行 Cluster.status({'extended':1}) 或将 extended 选项设置为 true 时,输出包括:
defaultReplicaSet对象的以下附加属性:GRProtocolVersion:InnoDB Cluster中使用的组复制协议版本。InnoDB Cluster自动管理所使用的组复制协议版本,有关更多信息,请参阅 InnoDB Cluster 与组复制协议。CommunicationStack:InnoDB Cluster正在使用的通信堆栈。可能的值为XCOM或MYSQL。有关详细信息,请参阅 配置组复制通信堆栈。groupName:组的名称,为UUID格式的值。groupViewChangeUuid:group_replication_view_change_uuid 的值。groupViewId:该组的当前视图标识符。该值取自 replication_group_member_stats 表的VIEW_ID列。paxosSingleLeader:显示 group_replication_paxos_single_leader 的值。这仅在MySQL Server 8.0.31或更高版本上可用,因为MySQL Shell需要 replication_group_communication_information 表中的WRITE_CONSENSUS_SINGLE_LEADER_CAPABLE提供的信息,该信息是在MySQL 8.0.31中引入的。
topology中每个对象的如下附加属性:fenceSysVars:包含由AdminAPI配置的受防护系统变量名称的列表。目前考虑的受保护系统变量是read_only、super_read_only和offline_mode。无论系统变量的值如何,都会列出它们。instanceErrors:每个实例的instanceErrors,显示每个实例可检测到的任何诊断信息。如,如果实例是辅助实例并且super_read_only变量未设置为ON,则会显示警告。此信息可用于排错。memberId:每个InnoDB Cluster成员的UUID。memberState:组复制插件报告的成员状态,请参阅 replication_group_members 表的MEMBER_STATE列。
https://dev.mysql.com/doc/mysql-shell/8.0/en/monitoring-innodb-cluster.html
当将 extended 设置为 2 或 3,可查看有关恢复和常规事务 I/O、Worker 应用线程统计信息和任何滞后的信息;应用协调线程统计信息(如果启用了并行复制应用线程);错误以及来自接收器和应用线程的其他信息。当设置 2 或 3 时,将打开与 InnoDB Cluster 中每个实例的连接,以便可以查询其他实例特定的统计信息。输出中包含的具体统计信息取决于实例的状态和配置以及服务器版本。此信息与 replication_group_member_stats 表中显示的信息匹配,请参阅匹配列的描述 以获取更多信息。ONLINE 实例的输出中包含事务部分。正在 RECOVERING 的实例在输出中包含恢复部分。当您将 extended 设置为 2 时,无论哪种情况,这些部分都可以包含以下内容:
appliedCount:参见COUNT_TRANSACTIONS_REMOTE_APPLIEDcheckedCount:请参阅COUNT_TRANSACTIONS_CHECKEDcommittedAllMembers:请参阅TRANSACTIONS_COMMITTED_ALL_MEMBERSconflictsDetectedCount:参见COUNT_CONFLICTS_DETECTEDinApplierQueueCount:参见COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUEinQueueCount:请参阅COUNT_TRANSACTIONS_IN_QUEUElastConflictFree:参见LAST_CONFLICT_FREE_TRANSACTIONproposedCount:参见COUNT_TRANSACTIONS_LOCAL_PROPOSEDrollbackCount:请参阅COUNT_TRANSACTIONS_LOCAL_ROLLBACK
当您将 extended 设置为 3 时,相当于将已弃用的 queryMembers 选项设置为 true,连接部分将显示来自 replication_connection_status 表的信息。可以包含以下内容:
currentlyQueueing部分包含有关当前排队的事务的信息:immediateCommitTimestamp:参见QUEUEING_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMPimmediateCommitToNowTime:参见QUEUEING_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP - NOW()originalCommitTimestamp:参见QUEUEING_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMPoriginalCommitToNowTime:参见QUEUEING_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP - NOW()startTimestamp:请参阅QUEUEING_TRANSACTION_START_QUEUE_TIMESTAMPtransaction:参见QUEUEING_TRANSACTIONlastHeartbeatTimestamp:参见LAST_HEARTBEAT_TIMESTAMP
astQueued部分包含有关最近排队的事务的信息:endTimestamp:参见LAST_QUEUED_TRANSACTION_END_QUEUE_TIMESTAMPimmediateCommitTimestamp:参见LAST_QUEUED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMPimmediateCommitToEndTime:参见LAST_QUEUED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP - NOW()originalCommitTimestamp:参见LAST_QUEUED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMPoriginalCommitToEndTime:参见LAST_QUEUED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP - NOW()queueTime:参见LAST_QUEUED_TRANSACTION_END_QUEUE_TIMESTAMP - LAST_QUEUED_TRANSACTION_START_QUEUE_TIMESTAMPstartTimestamp:参见LAST_QUEUED_TRANSACTION_START_QUEUE_TIMESTAMPtransaction:参见LAST_QUEUED_TRANSACTIONreceivedHeartbeats:参见COUNT_RECEIVED_HEARTBEATSreceivedTransactionSet:参见RECEIVED_TRANSACTION_SETthreadId:参见THREAD_ID
使用多线程的副本实例将包含 workers 部分,其中包含有关 worker 线程的信息,并与 replication_applier_status_by_worker 表显示的信息相匹配。
lastApplied部分显示有关worker应用线程的最后一个事务的以下信息:applyTime:参见LAST_APPLIED_TRANSACTION_END_APPLY_TIMESTAMP - LAST_APPLIED_TRANSACTION_START_APPLY_TIMESTAMPendTimestamp:参见LAST_APPLIED_TRANSACTION_END_APPLY_TIMESTAMPimmediateCommitTimestamp:参见LAST_APPLIED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMPimmediateCommitToEndTime:参见LAST_APPLIED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP - NOW()originalCommitTimestamp:参见LAST_APPLIED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMPoriginalCommitToEndTime:参见LAST_APPLIED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP - NOW()startTimestamp:参见LAST_APPLIED_TRANSACTION_START_APPLY_TIMESTAMPtransaction:参见LAST_APPLIED_TRANSACTION
currentlyApplying部分显示有关worker线程当前正在应用的事务的以下信息:immediateCommitTimestamp:参见APPLYING_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMPimmediateCommitToNowTime:参见APPLYING_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP - NOW()originalCommitTimestamp:参见APPLYING_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMPoriginalCommitToNowTime:参见APPLYING_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP - NOW()startTimestamp:参见APPLYING_TRANSACTION_START_APPLY_TIMESTAMPtransaction:参见APPLYING_TRANSACTION
LastProcessed部分包含有关worker线程处理的最后一个事务的以下信息:bufferTime:参见LAST_PROCESSED_TRANSACTION_END_BUFFER_TIMESTAMP - LAST_PROCESSED_TRANSACTION_START_BUFFER_TIMESTAMPendTimestamp:参见LAST_PROCESSED_TRANSACTION_END_BUFFER_TIMESTAMPimmediateCommitTimestamp:参见LAST_PROCESSED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMPimmediateCommitToEndTime:参见LAST_PROCESSED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP - LAST_PROCESSED_TRANSACTION_END_BUFFER_TIMESTAMPoriginalCommitTimestamp:参见LAST_PROCESSED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMPoriginalCommitToEndTime:参见LAST_PROCESSED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP - LAST_PROCESSED_TRANSACTION_END_BUFFER_TIMESTAMPstartTimestamp:参见LAST_PROCESSED_TRANSACTION_START_BUFFER_TIMESTAMPtransaction:参见LAST_PROCESSED_TRANSACTION
如果启用并行复制应用线程,则事务或恢复中的 worker 数组中的对象数量与配置的 worker 数量相匹配,并且会包含一个额外的协调器(coordinator)对象。显示的信息与 replication_applier_status_by_coordinator 表中的信息匹配。该对象可包含:
currentProcessing部分包含有关worker线程正在处理的事务的以下信息:immediateCommitTimestamp:参见PROCESSING_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMPimmediateCommitToNowTime:参见PROCESSING_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP - NOW()originalCommitTimestamp:参见PROCESSING_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMPoriginalCommitToNowTime:参见PROCESSING_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP - NOW()startTimestamp:参见PROCESSING_TRANSACTION_START_BUFFER_TIMESTAMPtransaction:参见PROCESSING_TRANSACTION
如果在 replication_applier_status_by_worker 表中检测到错误,worker 对象将具有以下信息:
lastErrno:参见LAST_ERROR_NUMBERlastError:参见LAST_ERROR_MESSAGElastErrorTimestamp:参见LAST_ERROR_TIMESTAMP
如果在 replication_connection_status 表中检测到错误,connection 对象将具有以下信息:
lastErrno:参见LAST_ERROR_NUMBERlastError:参见LAST_ERROR_MESSAGElastErrorTimestamp:参见LAST_ERROR_TIMESTAMP
如果在 replication_applier_status_by_coordinator 表中检测到错误,coordinator 对象将具有以下信息:
lastErrno:参见LAST_ERROR_NUMBERlastError:参见LAST_ERROR_MESSAGElastErrorTimestamp:参见LAST_ERROR_TIMESTAMP
7.7.3. 监控恢复操作
Cluster.status() 的输出显示有关处于 RECOVERING 状态的实例的恢复操作进度的信息。显示使用 MySQL Clone 或增量恢复进行恢复的实例的信息。将监控如下这些字段:
recoveryStatusText字段包括有关正在使用的恢复类型的信息。当MySQL Clone在工作时,该字段显示“Cloning in progress”。当增量恢复工作时,该字段显示“Distributed recovery in progress”。- 当使用
MySQL Clone时,恢复字段包括一个包含以下字段的字典:cloneStartTime:克隆进程开始的时间戳cloneState:克隆进程的状态currentStage:克隆进程当前达到的阶段currentStageProgress:克隆进程当前阶段占完成百分比currentStageState:当前阶段的状态
Cluster.status() 输出示例,为简洁起见进行了删剪:
...
"recovery": {
"cloneStartTime": "2019-07-15 12:50:22.730",
"cloneState": "In Progress",
"currentStage": "FILE COPY",
"currentStageProgress": 61.726837675213865,
"currentStageState": "In Progress"
},
"recoveryStatusText": "Cloning in progress",
...
- 当使用增量恢复并且
extended选项设置为1或更大时,recovery字段包括具有以下字段的字典:state:group_replication_recovery通道的状态recoveryChannel:执行增量恢复或恢复通道状态未关闭的实例将显示此字段。增量恢复利用接收器线程从源接收事务,应用程序线程将接收到的事务应用到实例上。提供以下信息:applierQueuedTransactionSetSize:当前排队等待应用的事务数量。applierState:复制应用(applier)线程的当前状态,ON或OFF。applierStatus:复制应用(applier)线程的当前状态。applierThreadState字段中显示的状态的聚合。可以是以下之一:APPLIED_ALL:没有排队的事务等待被应用APPLYING:有事务正在被应用ON:线程已连接并且没有排队的事务ERROR:应用事务时出现错误OFF:应用程序(applier)线程被禁用
applierThreadState:任何应用程序(applier)线程的当前状态。提供有关应用程序线程正在执行的操作的详细信息。有关详细信息,请参阅 复制 SQL 线程状态。receiverStatus:接收器线程的当前状态。receiveThreadState字段中显示的状态的聚合。可以是以下之一:ON:接收线程已成功连接并准备接收CONNECTING:接收器线程正在连接到源ERROR:接收事务时出现错误OFF:接收器线程已正常断开连接
receiverThreadState:接收器线程的当前状态。提供有关接收器线程正在执行的操作的详细信息。有关详细信息,请参阅 复制 I/O(接收器)线程状态。source:正在应用的事务的来源。
Cluster.status() 输出示例,为简洁起见进行了修剪:
...
"recovery": {
"recoveryChannel": {
"applierQueuedTransactionSetSize": 2284,
"applierStatus": "APPLYING",
"applierThreadState": "Opening tables",
"receiverStatus": "ON",
"receiverThreadState": "Queueing master event to the relay log",
"source": "ic-2:3306"
},
"state": "ON"
},
...
7.7.4. InnoDB Cluster 与 组复制协议
从 MySQL 8.0.16 开始,组复制有了组通信协议的概念,有关背景信息,请参阅 设置组的通信协议版本。组复制通信协议版本通常必须显式管理,并设置为适应您希望复制组支持的最旧的 MySQL Server 版本。但是,每当使用 AdminAPI 更改 InnoDB Cluster 拓扑时,InnoDB Cluster 都会自动且透明地管理其成员的通信协议版本。 InnoDB Cluster 始终使用当前已属于集群或正在加入集群的所有实例支持的最新通信协议版本。
- 当实例添加、删除、重新加入集群,或者对集群进行重新扫描或重启操作时,通信协议版本会自动设置为当前最旧的
MySQL Server实例支持的版本。 - 当您通过从
InnoDB Cluster中删除实例、升级它们(实例)并将它们添加回集群来执行滚动升级时,当旧MySQL Server版本的最后一个剩余实例从InnoDB Cluster中删除之前,通信协议版本会自动升级。
要查看 InnoDB Cluster 中使用的通信协议版本,请使用 Cluster.status() 函数并启用 extended 选项。通信协议版本在 GRProtocolVersion 字段中返回,前提是集群具有法定人数(quorum)并且没有无法访问的集群成员。
7.7.5. 检查 MySQL 实例版本
以下操作可以报告实例上运行的 MySQL Server 版本信息:
Cluster.status()Cluster.describe()Cluster.rescan()
该行为因 Cluster 对象会话的 MySQL Server 版本而异。
Cluster.status()如果满足以下任一要求,则为拓扑对象的每个实例JSON对象返回版本字符串属性:Cluster对象的当前会话版本为MySQL ≥ 8.0.11的版本。Cluster对象的当前会话正在运行MySQL <8.0.11的版本,但扩展extended设置为3(或已弃用的queryMembers为true)。
# 在运行版本 8.0.16 的实例上:
"topology": {
"ic-1:3306": {
"address": "ic-1:3306",
"mode": "R/W",
"readReplicas": {},
"role": "HA",
"status": "ONLINE",
"version": "8.0.16"
}
# 在运行版本 5.7.24 的实例上:
"topology": {
"ic-1:3306": {
"address": "ic-1:3306",
"mode": "R/W",
"readReplicas": {},
"role": "HA",
"status": "ONLINE",
"version": "5.7.24"
}
Cluster.describe()如果Cluster对象的当前会话是MySQL ≥ 8.0.11版本,则为拓扑对象的每个实例JSON对象返回版本字符串属性
# 在运行版本 8.0.16 的实例上:
"topology": [
{
"address": "ic-1:3306",
"label": "ic-1:3306",
"role": "HA",
"version": "8.0.16"
}
]
Cluster.rescan()如果Cluster对象的当前会话是MySQL ≥ 8.0.11版本,并且Cluster.rescan()操作检测到不属于该集群的实例,则将为newDiscoveredInstance对象的每个实例JSON对象返回版本字符串属性。
# 在运行版本 8.0.16 的实例上:
"newlyDiscoveredInstances": [
{
"host": "ic-4:3306",
"member_id": "82a67a06-2ba3-11e9-8cfc-3c6aa7197deb",
"name": null,
"version": "8.0.16"
}
]
7.8. 恢复与重启 InnoDB Cluster
本节介绍如何将服务器实例重新加入 InnoDB Cluster、从仲裁丢失中恢复 InnoDB Cluster 或在中断后重新启动它,以及在更改后重新扫描 InnoDB Cluster。
7.8.1. 将实例重新加入 InnoDB Cluster
若实例离开集群,如因为失去连接,并且由于某种原因无法自动重新加入集群,则可能需要在稍后阶段手动将其重新加入集群。要将实例重新加入集群,请执行 Cluster.rejoinInstance(instance) 指令。
:::alert-info
【Important】
如果实例的 super_read_only=ON,那么您可能需要确认 AdminAPI 可以设置 super_read_only=OFF。更多信息请参见 超级只读模式实例配置。
:::
若实例的配置未持久化(请参阅 持久化设置),则实例重启后,不会自动重新加入 InnoDB Cluster。解决方案是执行 cluster.rejoinInstance() 以便将实例再次添加到 InnoDB Cluster 中并确保更改得到持久化。只要将 InnoDB Cluster 配置保存到实例的选项文件(my.cnf)中,它就会自动重新加入 InnoDB Cluster。
如果您要重新加入以某种方式发生更改的实例,那么您可能必须修改该实例才能使重新加入过程正常工作。如,当您恢复 MySQL Enterprise Backup 备份时,server_uuid 会发生变化。尝试重新加入此类实例会失败,因为 InnoDB Cluster 实例由 server_uuid 变量唯一标识。在这种情况下,必须从 InnoDB Cluster 元数据中删除有关实例的旧 server_uuid 的信息,然后必须执行 Cluster.rescan() 以使用新的 server_uuid 将实例添加到元数据中。例如:
cluster.removeInstance("root@instanceWithOldUUID:3306", {force: true}) cluster.rescan()
在此情况下,您必须为 Cluster.removeInstance() 方法指定 force 选项,因为从 InnoDB Cluster 集群的角度来看该实例是无法访问的,并且我们无论如何都希望将其从 InnoDB Cluster 元数据中删除。
rejoinInstance() 还会检查实例使用的通信堆栈并确保 InnoDB Cluster 支持它。如果 InnoDB Cluster 支持通信堆栈,则 rejoinInstance() 会将实例添加到 InnoDB Cluster 中。
7.8.2. 从仲裁丢失中恢复集群
若一个实例(或多个实例)发生故障,则 InnoDB Cluster 可能会失去其法定人数(quorum),即失去为新的 Primary 实例投票的能力。当过多的实例发生故障以致组成 InnoDB Cluster 的大多数实例无法对组复制操作进行投票时,就会发生这种情况。请参阅 Fault-tolerance。当 InnoDB Cluster 失去仲裁时,您无法再处理集群的写入事务,也无法通过添加、重新加入或删除实例来更改集群的拓扑。但是,如果您有一个包含 InnoDB Cluster 元数据的在线实例,则可以通过仲裁恢复集群。这里假设您可以连接到包含 InnoDB Cluster 元数据的实例,并且该实例可以联系到您将要用于恢复 InnoDB Cluster 的其他实例。
:::alert-info
【Important】
此操作具有潜在风险,因为如果使用不当,可能会造成脑裂情况,应将其视为最后的手段。绝对确保该复制组中没有任何分区仍在网络中的某个位置运行,但无法从您的位置进行访问。
:::
连接到包含 InnoDB Cluster 元数据的实例,然后使用 Cluster.forceQuorumUsingPartitionOf(instance) 操作,该操作将根据 instance 上的元数据来恢复 InnoDB Cluster 集群,然后从 instance 定义的角度来看,所有处于 ONLINE 状态的实例都被添加到已恢复的 InnoDB Cluster 集群中。
mysql-js> cluster.forceQuorumUsingPartitionOf("icadmin@ic-1:3306")
Restoring replicaset 'default' from loss of quorum, by using the partition composed of [icadmin@ic-1:3306]
Please provide the password for 'icadmin@ic-1:3306': ******
Restoring the InnoDB cluster ...
The InnoDB cluster was successfully restored using the partition from the instance 'icadmin@ic-1:3306'.
WARNING: To avoid a split-brain scenario, ensure that all other members of the replicaset
are removed or joined back to the group that was restored.
如果实例未自动添加到 InnoDB Cluster 集群,例如其设置未持久化,请使用 Cluster.rejoinInstance() 手动将实例添加回 InnoDB Cluster。
恢复的 InnoDB Cluster 集群可能不会、也不必包含组成集群的所有原始实例。例如,如果原始 InnoDB Cluster 由以下 5 个实例组成:
- ic-1
- ic-2
- ic-3
- ic-4
- ic-5
InnoDB Cluster 集群出现裂脑场景,ic-1、ic-2、ic-3 组成一个分区,而 ic-4 和 ic-5 组成另一个分区。如果您连接到 ic-1 并执行 Cluster.forceQuorumUsingPartitionOf('icadmin@ic-1:3306') 来恢复集群,则恢复的集群将包含以下 3 个实例:
- ic-1
- ic-2
- ic-3
因为 ic-1 将 ic-2 和 ic-3 视为 ONLINE,而看不到 ic-4 和 ic-5。
7.8.3. 从严重中断中重启集群
如果您的 InnoDB Cluster 集群遇到完全中断,您可以使用 dba.rebootClusterFromCompleteOutage() 重新配置它。此操作使您能够连接到集群的 MySQL 实例之一并使用其元数据来恢复集群。
完全中断意味着所有成员实例上的组复制都已停止。
:::alert-info
【Note】
确保在运行 dba.rebootClusterFromCompleteOutage() 之前启动 InnoDB Cluster 集群所有成员。如果任何成员无法访问,该命令将失败。
如果 InnoDB Cluster 集群已 INVALIDATED 并且是 ClusterSet 的成员,则忽略此检查。
:::
连接到最新的实例并运行以下命令:
JS> var cluster = dba.rebootClusterFromCompleteOutage()
如果所有成员都设置了相同的 GTID 集,则您当前连接的成员将成为 Primary 成员。请参阅 使用 rebootClusterFromCompleteOutage 选择 Primary 节点。
dba.rebootClusterFromCompleteOutage() 操作遵循以下步骤以确保正确重新配置集群:
InnoDB Cluster元数据和拓扑是从当前实例中检索的。- 如果
InnoDB Cluster一个成员处于RECOVERING或ERROR状态,且所有其他成员都处于OFFLINE或ERROR状态,则dba.rebootClusterFromCompleteOutage()会尝试停止该成员上的组复制。如果组复制无法停止,该命令将报错并停止。 - 在
MySQL Shell当前连接到的实例上检查找到的InnoDB Cluster元数据,以查看它是否包含GTID Superset。如果当前连接的实例不包含GTID Superset,则操作将中止。参考 GTID Superset。 - 如果实例包含
Superset,则根据该实例中存储的元数据恢复集群。 MySQL Shell检查InnoDB Cluster中的哪些实例当前可访问,如果任何成员当前不可访问,则失败。使用force选项可以绕过此检查。这将使用剩余的可连接(contactable)成员重新启动集群。参考 Force Option。- 同样,
MySQL Shell会检测当前无法访问的实例。如果InnoDB Cluster以前的成员当前无法访问,则无法作为dba.rebootClusterFromCompleteOutage()命令的一部分向InnoDB Cluster集群添加或从其中删除成员。 - 如果
super_read_only在InnoDB Cluster集群的Primary实例上被启用,则在单主模式下,super_read_only将被禁用。
7.8.3.1. GTID Superset
要重启 InnoDB Cluster 集群,您必须连接到具有 GTID Superset 的成员,这意味着该成员是在 InnoDB Cluster 中断之前,已应用了最多事务的实例。
要确定哪个成员具有 GTID Superset,请执行以下操作之一:
- 连接到实例并使用
dryRun: true选项,运行dba.rebootClusterFromCompleteOutage()。生成的报告将返回类似于以下内容的信息:
Switching over to instance '127.0.0.1:4001' to be used as seed.
这表示该实例是具有 GTID Superset 的 InnoDB Cluster 成员。对具有较低 GTID set(可理解为不具有 GTID Superset)的成员运行 dba.rebootClusterFromCompleteOutage() 会导致错误。
- 依次连接各个实例,并在
SQL模式下运行以下命令:
SHOW VARIABLES LIKE 'gtid_executed';
已应用了 最大 GTID 事务集 的实例中包含 GTID Superset。
:::alert-info
【Note】
通过使用 force 选项运行 dba.rebootClusterFromCompleteOutage(),可以覆盖以上行为。该选项会强制使具有较低 GTID set 的实例成为 Primary 成员,并丢弃未包含在所选成员的 GTID set 中的任何事务。
:::
如果上述过程失败,并且 InnoDB Cluster 元数据已严重损坏,您可能需要通过 dba.dropMetadataSchema() 删除元数据,并从头开始重新创建 InnoDB Cluster 集群。
:::alert-danger
【Note】
因为 dba.dropMetadataSchema() 方法无法撤消,故只能作为无法恢复集群时的最后手段。
:::
如果您在 InnoDB Cluster 集群中正在使用 MySQL Router,则当您删除元数据时,所有当前连接都将被删除,并且禁止新连接。这会导致完全中断。
7.8.3.2. Options
dba.rebootClusterFromCompleteOutage() 有以下选项:
force: true | false (default):如果为true,则即使无法访问InnoDB Cluster集群的某些成员,或者选择的Primary实例具有发散或较低的GTID_SET,也必须执行该操作。请参阅 Force Option。dryRun: true | false (default):执行命令的所有验证和步骤,但不进行任何更改。完成后会显示一份报告。请参阅 测试 restartClusterFromCompleteOutage。primary:表示必须将参数instance指定的实例选为Primary节点。请参阅 使用 rebootClusterFromCompleteOutage 选择 Primary 节点。switchCommunicationStack: mysql | xcom:InnoDB Cluster集群重启后使用的组复制协议栈。请参阅 配置组复制通信堆栈。ipAllowList:使用XCOM协议栈时,组复制的主机白名单列表。localAddress:使用XCOM协议栈时,使用的组复制本地地址,该值将替代自动生成的地址。
7.8.3.3. Force Option
force 选项使您能够忽略 InnoDB Cluster 集群成员的可用性或所选成员中 GTID set 的差异并重启集群,即强制重启。例如,强制重启集群 myCluster:
JS> var cluster = dba.rebootClusterFromCompleteOutage("myCluster",{force: true})
在以下情况下不允许使用 force 选项:
- 该
Cluster属于ClusterSet并且处于INVALIDATED状态;或者Primary Cluster不处于全局状态OK, - 该
Cluster属于ClusterSet,是Primary Cluster,并且处于INVALIDATED状态。
无法使用 rebootClusterFromCompleteOutage 添加或重新加入实例。如果您使用 force 选项忽略无法访问的成员并重启 InnoDB Cluster 集群,则必须使用 cluster.rejoinInstance() 将无法访问的成员添加到集群。
7.8.3.4. 使用 rebootClusterFromCompleteOutage 选择主节点
您可以通过以下方式之一定义 InnoDB Cluster 集群 Primary 节点:
- 在
dba.rebootClusterFromCompleteOutage()命令中指定primary选项。如,重启集群myCluster并将本地端口4001上运行的成员设置为Primary成员:
var cluster = dba.rebootClusterFromCompleteOutage("myCluster",{primary: "127.0.0.1:4001"})
- 通过在
GTID set低于其他成员的InnoDB Cluster集群成员上使用primary选项和force选项。
7.8.3.5. 测试 restartClusterFromCompleteOutage
您可以使用 dryRun 选项来测试更改。此选项验证命令及其选项并生成结果日志。如果建议的更改存在问题,则会引发异常。
以下示例显示了通过选项 dryRun 重启集群 myCluster,并将本地端口 4001 上运行的实例设置为集群的 Primary 成员,所返回的日志消息:
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.
7.8.3.6. ClusterSet 和 ReplicaSet 的注意事项
restartClusterFromCompleteOutage 执行以下检查,如果 InnoDB Cluster 集群不满足要求,则会生成警告:
- 确认副本集群(
Replica Cluster)未被从ClusterSet中强制删除。 - 确认
ClusterSet的Primary集群可访问。 - 检查
InnoDB Cluster集群中是否存在非查看更改日志事件 (View Change Log Events,VCLE) 的错误事务。请参阅 分布式恢复的工作原理。 - 确认
InnoDB Cluster集群的已执行事务集(GTID_EXECUTED)不为空。
该命令自动将副本集群(Replica Cluster)重新加入 ClusterSet,确保为所有集群成员配置 ClusterSet 复制通道。
7.8.3.7. 交换通信堆栈
您可以在 dba.rebootClusterFromCompleteOutage() 操作期间,通过选项 switchCommunicationStack 切换通信堆栈。如:
js> dba.rebootClusterFromCompleteOutage("testcluster", {switchCommunicationStack: "mysql"})
从 MYSQL 协议切换到 XCOM 需要 localAddress 的附加网络地址,并且可能还需要您定义 ipAllowList 的值。
7.8.4. 重新扫描集群
如果您在 AdminAPI 命令之外对 InnoDB Cluster 集群进行配置更改,如:
- 通过手动更改实例的配置来解决配置问题;
- 在实例丢失后,需要更新
InnoDB Cluster元数据,使其与当前实例的配置相匹配。
在这些情况下,请使用 Cluster.rescan() 操作,该操作使您能够手动或使用交互式向导更新 InnoDB Cluster 元数据。 Cluster.rescan() 操作可以检测未在元数据中注册的新活动(active)实例并添加它们,或者仍然在元数据中注册的过时实例(inactive)并将其删除。您可以根据命令找到的实例自动更新元数据,也可以指定要添加到元数据或从元数据中删除的实例地址列表。您还可以更新存储在元数据中的拓扑模式,如在 AdminAPI 外部从单主模式切换为多主模式之后。
该命令的语法是 Cluster.rescan([options])。options 字典支持以下内容:
interactive:布尔值,用于在命令执行中禁用或启用向导。控制是否提供提示和确认。默认值等于MySQL Shell向导模式,由shell.options.useWizards指定。addInstances:列出要添加到元数据的新活动(active)实例的连接数据,或设置为 “auto(不区分大小写)” 表示自动将丢失的实例添加到元数据。。- 列表中指定的实例将被直接添加到元数据中,而不为用户提示确认。
- 在交互模式下,系统会提示您确认添加未包含在
addInstances选项中的新发现的实例。 - 在非交互模式下,未包含在
addInstances选项中的新发现的实例会在输出中报告,但不会提示您添加它们。
removeInstances:列出要从元数据中删除的过时(inactive)实例的连接数据,或设置为 “auto(不区分大小写)”表示自动从元数据中删除过时的实例。- 列表中指定的实例将被直接从元数据中删除,且不为用户提示确认。
- 在交互模式下,系统会提示您确认删除未包含在
removeInstances选项中的过时实例。 - 在非交互模式下,
removeInstances选项中未包含的过时实例会在输出中报告,但不会提示您删除它们。
updateTopologyMode:布尔值,用于指示是否更新(true)元数据中的拓扑模式(单主或多主)以匹配InnoDB Cluster集群正在使用的拓扑模式。默认值false表示不更新元数据。- 如果该值为
true,则将InnoDB Cluster元数据与组复制当前使用的模式进行比较,并在必要时更新元数据。在AdminAPI外部更改集群的拓扑模式后,需使用此选项更新元数据。 - 如果该值为
false,则不更新InnoDB Cluster元数据中的拓扑模式,即使它与集群的组复制使用不同的拓扑。 - 如果未指定该选项,并且元数据中的拓扑模式与集群的
Group Replication组使用的拓扑不同,则:- 交互模式下,系统会提示您确认元数据中拓扑模式的更新。
- 在非交互模式下,如果集群的
Group Replication组使用的拓扑与InnoDB Cluster元数据之间存在差异,则会报告该差异,并且不会对元数据进行任何更改。
- 当
InnoDB Cluster元数据拓扑模式更新为匹配组复制模式时,所有实例上的auto-increment设置都会被更新,如 InnoDB Cluster 与自增中所述。
- 如果该值为
updateViewChangeUuid:布尔值,用于指示是否应为集群实例上的 group_replication_view_change_uuid 系统变量生成和设置值。此系统变量为组生成的视图更改事件提供备选(alternative)的UUID。对于MySQL ≥ 8.0.27的实例,对于属于InnoDB ClusterSet一部分的InnoDB Cluster,group_replication_view_change_uuid系统变量是必需的,并且必须在集群中的所有成员服务器上设置为相同的值。从MySQL Shell ≥ 8.0.27开始,使用dba.createCluster()命令创建的InnoDB Cluster会为所有成员服务器生成并设置group_replication_view_change_uuid系统变量的值。在MySQL Shell < 8.0.27创建的InnoDB Cluster可能未设置该系统变量,但创建InnoDB ClusterSet过程中会检查此系统变量,如果不存在,则会失败并显示警告。
updateViewChangeUuid默认设置为false,如果未找到系统变量或在任何实例上都不匹配,则会返回一条警告消息,让您知道必须为该系统变量设置一个值并重启InnoDB Cluster。如果将updateViewChangeUuid设置为true,则重新扫描操作会在所有成员服务器上生成并设置group_replication_view_change_uuid的值,之后您必须重启InnoDB Cluster集群才能实施更改。在MySQL Shell < 8.0.29,此选项不可用,Cluster.rescan()命令会自动生成并设置系统变量d的值,如同设置为true一样,之后需要重启InnoDB Cluster集群才能实施更改。重启InnoDB Cluster集群后,您可以重试InnoDB ClusterSet创建过程。upgradeCommProtocol:布尔值,用于指示组复制通信协议版本是否应升级(true)到集群中最低MySQL版本的实例所支持的版本。默认值false,不升级通信协议版本。MySQL Shell < 8.0.26的AdminAPI操作会尽可能自动升级,但该过程可能会导致集群延迟。从MySQL Shell ≥ 8.0.26开始,如果通信协议版本可以升级,导致拓扑更改的AdminAPI操作会返回一条消息,您可以使用此选项在合适的时间进行升级。建议升级到组复制通信协议的最高可用版本,以支持最新功能。如大型事务的消息碎片。有关详细信息,请参阅 设置组的通信协议版本。- 如果该值为
true,则组复制通信协议版本将升级到集群中最低MySQL版本实例所支持的协议版本。 - 如果该值为
false(默认值),则不会升级组复制的通信协议版本。
- 如果该值为
7.8.5. 隔离集群
紧急故障转移后,ClusterSet 各部分之间存在事务集不同的风险,您必须隔离 InnoDB Cluster 集群以防止产生写入流量。尽管您主要在属于 ClusterSet 的 InnoDB Cluster 集群上使用隔离,但也可以隔离独立集群,使其免受读写流量的影响。
从 MySQL Shell ≥ 8.0.28 开始,提供了 3 种防护操作:
<Cluster>.fenceWrites():禁止向ClusterSet的Primary集群中写入。<Cluster>.unfenceWrites():恢复向InnoDB Cluster的写入。<Cluster>.fenceAllTraffic():隔离集群,使其免受所有(读写)流量的影响。
有关更多详细信息,请参阅 InnoDB ClusterSet 中的 Fencing Clusters。
7.9. 修改或解散 InnoDB Cluster
本节介绍如何更改 InnoDB Cluster 拓扑(单主或多主)、如何从 InnoDB Cluster 中删除服务器实例,以及如何解散不再需要的 InnoDB Cluster。
7.9.1. 更改 InnoDB Cluster 的拓扑
默认情况下,InnoDB Cluster 以单主模式运行,其中仅有 1 台 Primary 服务器接受读写查询(R/W),集群中的其余实例仅接受读查询(R/O) 。当将 InnoDB Cluster 集群配置为在多主模式下运行时,集群中的所有实例都是 Primary 实例,这意味着它们可同时接受读写查询 (R/W)。如果集群的所有实例都运行 MySQL ≥ 8.0.15,您可以在 InnoDB Cluster 集群在线时更改集群的拓扑。在 MySQL < 8.0.15 的版本中,需要完全解散并重新创建集群才能进行拓扑更改。上述描述,使用通过 Configuring an Online Group 中描述的 group action coordinator 功能来实现,因此您应该遵守 Configuring an Online Group 的规则。
:::alert-info
【Note】
多主模式被认为是一种高级模式。
:::
通常,当当前 Primary 节点意外离开集群(如意外停机)时,单主集群会选举新的 Primary 节点。选举过程通常在当前的辅助节点中自动选择一个节点成为新的 Primary 节点。要覆盖选举过程并强制将复制组中的特定服务器实例选择为新的 Primary 实例,请使用 Cluster.setPrimaryInstance(instance[, options) 函数,其中 instance 指定与应成为新 Primay 实例的连接信息。从 MySQL Shell ≥ 8.0.29,可以使用 runningTransactionsTimeout 选项为该函数添加 0-3600 秒之间的超时。当设置超时选项后,该命令发出后进入 InnoDB Cluster 的事务将被拒绝。
可以使用以下操作切换 InnoDB Cluster 集群的运行模式(有时称为 拓扑):
Cluster.switchToMultiPrimaryMode():将InnoDB Cluster集群切换到多主模式。所有实例都将成为Primary实例。Cluster.switchToSinglePrimaryMode([instance]):将InnoDB Cluster集群切换到单主模式。如果指定了参数instance,则instance定义的实例将成为Primary实例,所有其他实例将成为辅助实例。如果未指定instance,则具有最高成员权重的实例将成为新的Primary实例;如果权重相同,则具有最低 UUID的实例将成为新的Primary实例。
7.9.2. 从 InnoDB Cluster 中删除实例
可以随时使用 Cluster.removeInstance(instance) 方法从 InnoDB Cluster 集群中删除实例。如下例所示:
mysql-js> cluster.removeInstance('root@localhost:3310')
The instance will be removed from the InnoDB cluster. Depending on the instance
being the Seed or not, the Metadata session might become invalid. If so, please
start a new session to the Metadata Storage R/W instance.
Attempting to leave from the Group Replication group...
The instance 'localhost:3310' was successfully removed from the cluster.
可以指定 interactive 选项以交互模式运行命令,以从 InnoDB Cluster 集群中删除实例。在交互模式下,系统会提示您继续删除(或不删除)实例,以防无法访问该实例。cluster.removeInstance() 操作可确保从所有 ONLINE 集群成员以及实例本身的元数据中删除该实例。使用此操作无法删除InnoDB Cluster 中最后一个保持 ONLINE 状态的实例。
当要删除的实例仍具有需要应用的事务时,AdminAPI 将等待 MySQL Shell dba.gtidWaitTimeout 选项配置的秒数(默认 60 秒),以应用事务 (GTID)。有关更改默认值的信息,请参阅第 13.4 节“配置 MySQL Shell 选项”。如果在等待应用事务时达到 dba.gtidWaitTimeout 定义的超时值并且 force=false(或未定义),则会发出错误并中止删除操作。如果在等待应用事务时达到 dba.gtidWaitTimeout 定义的超时值,并且 force=true,则操作将继续,不会出现错误,并从 InnoDB Cluster 集群中删除实例。
:::alert-info
【Important】
仅当想要忽略任何错误(如未处理的事务或无法访问的实例)并且不打算在集群中重用该实例时,才应将 force 选项与 Cluster.removeInstance(instance) 一起使用。从集群中删除实例时忽略错误可能会导致实例与集群不同步,从而阻止该实例稍后重新加入集群。仅当计划不再将实例与 InnoDB Cluster 集群一起使用时才使用 force 选项,在所有其他情况下,应始终尝试恢复实例,并且仅在实例可用且运行状况良好(即状态为 ONLINE)时将其删除。
:::
7.9.3. 解散 InnoDB Cluster
要解散 InnoDB Cluster,请连接到 RW 实例(如单主集群中的 Primary 实例),然后使用 Cluster.dissolve() 命令。这将删除与 InnoDB Cluster 集群关联的所有元数据和配置,并禁用实例上的组复制,但不会删除实例之间已复制的任何数据。
:::alert-info
【Important】
Cluster.dissolve() 操作无法撤销。要再次创建 InnoDB Cluster 集群,请使用 dba.createCluster()。
:::
Cluster.dissolve() 操作只能配置 ONLINE 或可达(reachable)的实例。如果发出 Cluster.dissolve() 命令的成员无法联系到集群的其他成员,您必须决定如何进行解散(dissolve)操作。如果有机会将被识别为缺失(missing)的任何实例重新加入 InnoDB Cluster 集群中,强烈建议取消解散(dissolve)操作并首先将缺失的实例重新联机(ONLINE),然后再继续解散操作。这确保了所有实例都可以正确更新其元数据,并且不会出现裂脑情况。但是,如果集群中无法访问的实例已永久离开集群,则只能强制执行解散操作,这意味着丢失的实例将被忽略,只有在线(ONLINE)实例会受到该操作的影响。
:::alert-danger
【Warning】
强制解散操作忽略集群实例可能会导致在解散操作执行期间,无法访问的实例仍在继续运行,从而产生裂脑的风险。仅当您确定忽略的实例不可能再次联机时,才强制执行解散操作来忽略已丢失的实例。
:::
在交互模式下,如果在解散操作执行期间无法访问集群成员,则会显示如下的交互提示:
mysql-js> Cluster.dissolve()
The cluster still has the following registered instances:
{
"clusterName": "testCluster",
"defaultReplicaSet": {
"name": "default",
"topology": [
{
"address": "ic-1:3306",
"label": "ic-1:3306",
"role": "HA"
},
{
"address": "ic-2:3306",
"label": "ic-2:3306",
"role": "HA"
},
{
"address": "ic-3:3306",
"label": "ic-3:3306",
"role": "HA"
}
]
}
}
WARNING: You are about to dissolve the whole cluster and lose the high
availability features provided by it. This operation cannot be reverted. All
members will be removed from the cluster and replication will be stopped,
internal recovery user accounts and the cluster metadata will be dropped. User
data will be maintained intact in all instances.
Are you sure you want to dissolve the cluster? [y/N]: y
ERROR: The instance 'ic-2:3306' cannot be removed because it is on a '(MISSING)'
state. Please bring the instance back ONLINE and try to dissolve the cluster
again. If the instance is permanently not reachable, then you can choose to
proceed with the operation and only remove the instance from the Cluster
Metadata.
Do you want to continue anyway (only the instance metadata will be removed)?
[y/N]: y
Instance 'ic-3:3306' is attempting to leave the cluster... Instance 'ic-1:3306'
is attempting to leave the cluster...
WARNING: The cluster was successfully dissolved, but the following instance was
skipped: 'ic-2:3306'. Please make sure this instance is permanently unavailable
or take any necessary manual action to ensure the cluster is fully dissolved.
在此示例中,InnoDB Cluster 由 3 个实例组成,其中一个实例(如 ic-2:3306)在发出解散操作时处于离线状态,错误被捕获。您可以选择如何继续。在这种情况下,丢失的 ic-2:3306 实例将被忽略,并且可访问的成员的元数据将被更新。
当 MySQL Shell 以非交互模式(如批处理)运行时,您可以为 Cluster.dissolve() 操作指定 force 选项。要强制解散操作忽略任何无法访问的实例,请发出:
mysql-js> Cluster.dissolve({force: true})
任何可以访问的实例都会从 InnoDB Cluster 集群中删除,而任何无法访问的实例都会被忽略。本节中有关强制从 InnoDB Cluster 集群中删除丢失实例的警告同样适用于这种强制解散操作的技术。
还可以为 Cluster.dissolve() 操作指定 interactive 选项,来覆盖 MySQL Shell 运行的模式。如,在运行批处理脚本时显示交互式提示:
mysql-js> Cluster.dissolve({interactive: true})
MySQL Shell 选项 dba.gtidWaitTimeout 配置了 Cluster.dissolve() 操作在从 InnoDB Cluster 集群中删除目标实例之前等待应用集群事务的超时时间,但前提是目标实例处于 ONLINE 状态。如果目标实例应用事务超时,则会发出错误并种植解散操作。除非使用了 force: true 选项跳过错误,强制解散 InnoDB Cluster。
:::alert-info
【Note】
发出 cluster.dissolve() 后,已分配给 Cluster 对象的任何变量都将失效。
:::
7.10. 升级 InnoDB Cluster
本节介绍如何升级 InnoDB Cluster 集群。升级 InnoDB Cluster 的大部分过程都是按照 Upgrading Group Replication 中的相同方式升级 MySQL 实例。本节重点介绍升级 InnoDB Cluster 的其他注意事项。在开始升级之前,您可以使用 MySQL Shell 升级检查器实用程序 来验证实例是否已准备好升级。
:::alert-info
【Important】
由于元数据查询中出现错误,MySQL Shell 8.0.27 无法用于管理运行 MySQL Server 8.0.25 的 InnoDB Cluster。要解决此问题,请在 InnoDB Cluster 成员实例上将 MySQL Server 升级到 8.0.26 或 8.0.27 版本,然后再在 InnoDB Cluster 集群中使用 MySQL Shell 8.0.27。该问题将在 MySQL Shell 8.0.28 中得到修复。
:::
从版本 8.0.19 开始,如果您尝试针对 InnoDB Cluster 集群引导 MySQL Router 并且发现元数据版本为 0.0.0,这表明元数据升级正在进行中,并且引导失败。等待元数据升级完成,然后再尝试再次引导。当 MySQL Router 正常运行(不是引导)并且发现元数据版本为 0.0.0(正在进行升级)时,MySQL Router 不会继续刷新它即将开始的元数据。相反,MySQL Router 继续使用它缓存的最后一个元数据。所有现有的用户连接都会得到维护,并且任何新连接都会根据缓存的元数据进行路由。当元数据版本不再是 0.0.0 时,元数据刷新将重新启动。在常规(非引导)模式下,MySQL Router 使用版本 1.x.x 和 2.x.x 的元数据。版本可能会在 TTL 刷新之间发生变化。此更改可确保升级 InnoDB Cluster 集群时路由(routing)继续进行。
尽管 InnoDB Cluster 集群中可能有运行多个 MySQL 版本的实例,如版本 5.7 和 8.0。不建议长期使用这种版本混合的 InnoDB Cluster。例如,在使用不同版本的 InnoDB Cluster 集群中,运行 5.7 的实例离开集群,然后使用 MySQL Clone 进行恢复操作,运行较低版本的实例无法再加入 InnoDB Cluster,因为需要 BACKUP_ADMIN 权限。运行具有多个版本的 InnoDB Cluster 集群旨在作为一种临时情况,以帮助从一个版本迁移到另一个版本,不适合长期使用。
7.10.1. InnoDB Cluster 升级
要升级 InnoDB Cluster 中的服务器实例,请完成以下步骤:
- 升级
MySQL Router - 升级
MySQL Shell - 升级
MySQL Server - 升级后状态检查
检查已安装的二进制文件的版本:
mysqlrouter --version:检查安装的MySQL Router版本。mysqlsh --version:检查安装的MySQL Shell版本。mysqld --version:检查安装的MySQL Server版本。
7.10.1.1. 升级 MySQL Router
要升级 MySQL Router,请完成以下步骤:
- 停止 MySQL Router
在 Unix 系统上,如果您使用可选的 --directory 引导选项指定安装路径,则会在 --directory 指定的位置生成 router 所需的目录和文件,其中包含 stop.sh。导航到该目录并发出以下命令:
./stop.sh
在 Microsoft Windows 上,如果使用可选的 --directory 引导选项指定安装路径,则会在 --directory 指定的位置生成 router 所需的目录和文件,其中包含 stop.ps1。导航到该目录并发出以下命令:
.\stop.ps1
或者在使用 systemd 的 Linux 系统上,通过发出以下命令停止 MySQL Router 服务:
systemctl stop mysqlrouter.service
或者,也可 kill 掉 mysqlrouter 相关的进程 ID。
-
获取并安装最新版本的 MySQL Router。
-
启动 MySQL Router
在 Unix 系统上,如果您使用可选的 --directory 引导选项指定安装路径,则会在 --directory 指定的位置生成 router 所需的目录和文件,其中包含 start.sh。导航到该目录并发出以下命令:
./start.sh
如果新的 MySQL Router 路径已更改,则必须更新 start.sh 脚本以反映该路径。
#!/bin/bash
basedir=/tmp/myrouter
ROUTER_PID=$basedir/mysqlrouter.pid /usr/bin/mysqlrouter -c $basedir/mysqlrouter.conf &
disown %-
如果您手动升级 MySQL Router,而不是使用包管理,则可更新 basedir=。如果再次引导 MySQL Router,将重新生成 start.sh 脚本。
或者在使用 systemd 的 Linux 系统上,通过发出以下命令启动 MySQL Router 服务:
systemctl start mysqlrouter.service
在 Microsoft Windows 上,如果您使用可选的 --directory 引导选项指定安装路径,则会在 --directory 指定的位置生成 router 所需的目录和文件,其中包含 start.ps1。导航到该目录并发出以下命令:
.\start.ps1
使用新的二进制文件启动 MySQL Router 时,通过发出以下命令检查 MySQL Router 的版本是否已升级:
mysqlrouter --version
7.10.1.2. 升级 MySQL Shell
通过安装新的二进制文件并停止和启动 MySQL Shell 来升级 MySQL Shell:
-
获取并安装最新版本的
MySQL Shell。 -
在
MySQL Shell命令行中执行\q,停止并退出MySQL Shell: -
通过执行
mysqlsh,重新启动 MySQL Shell -
- 要升级
InnoDB Cluster的元数据,请将MySQL Shell 的全局会话连接到InnoDB Cluster集群,并使用dba.upgradeMetadata()操作升级InnoDB Cluster集群的元数据。如果InnoDB Cluster集群已使用最新版本,元数据升级可能不会执行任何操作。
- 要升级
7.10.1.3. 升级 MySQL Server
https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-innodb-cluster-upgrade-rolling.html
通过在升级 Primary 实例之前升级所有辅助实例来升级 MySQL Server。
:::alert-info
【升级 MySQL Server 是可选的】
MySQL Server 升级比升级 MySQL Shell 和 MySQL Router 产生的影响更大。另外,即使 MySQL Server 不是最新版,你也应该始终将 MySQL Shell 和 MySQL Router 保持在最新版本;对于 InnoDB Cluster 和 ReplicaSet 环境来说都是如此。
:::
-
通过发出以下命令之一停止 MySQL Server
- 如果
MySQL Server使用systemd,执行systemctl stop mysqld停止MySQL Server - 如果
MySQL Server使用init.d,执行/etc/init.d/mysql stop停止MySQL Server - 如果
MySQL Server使用service,执行service mysql stop停止MySQL Server - 如果在
Microsoft Windows上部署MySQL Server,执行mysqladmin -u root -p shutdown停止MySQL Server
- 如果
-
获取并安装最新版本的
MySQL Server -
通过发出以下命令之一启动 MySQL Server
- 如果
MySQL Server使用systemd,执行systemctl start mysqld启动MySQL Server - 如果
MySQL Server使用init.d,执行/etc/init.d/mysql start启动MySQL Server - 如果
MySQL Server使用service,执行service mysql start启动MySQL Server - 如果在
Microsoft Windows上部署MySQL Server,执行mysqld启动MySQL Server
- 如果
-
当所有辅助实例升级后,升级
Primary实例以完成升级过程。
7.10.1.4. 升级后状态检查
升级 MySQL Router、MySQL Shell 和 MySQL Server 之后:
- 通过发出
<Cluster>.status()检查InnoDB Cluster集群。有关<Cluster>.status()的更多信息,请参阅 使用 Cluster.status() 检查集群状态。 - 解决
<Cluster>.status()操作返回的clusterErrors和statusText。
这些命令可使您检查升级是否成功以及是否需要完成额外的步骤。额外的步骤取决于;升级跳过多少个版本、要升级哪个版本以及要从哪个版本开始升级。
- 通过发出
<Cluster>.status()检查每个InnoDB Cluster的状态。
在以下示例中,<Cluster>.status({extended: true})用于提供有关InnoDB Cluster集群状态的更详细信息,返回两个问题:
mysqlsh> <Cluster>.status({extended: true});
{
"clusterName": "MyCluster",
"defaultReplicaSet": {
"GRProtocolVersion": "8.0.16",
"groupName": "459ec434-8926-11ec-b8c3-02001707f44a",
"groupViewChangeUuid": "AUTOMATIC",
"groupViewId": "16443558036060755:13",
"name": "default",
"ssl": "REQUIRED",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"example-el7-1644251369:33311": {
"address": "example-el7-1644251369:33311",
"applierWorkerThreads": 4,
"fenceSysVars": [],
"instanceErrors": [
"NOTE: instance server_id is not registered in the metadata.
Use cluster.rescan() to update the metadata.",
"NOTE: The required parallel-appliers settings are not enabled on the instance.
Use dba.configureInstance() to fix it."
],
"memberId": "247131ab-8926-11ec-850b-02001707f44a",
"memberRole": "PRIMARY",
"memberState": "ONLINE",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.28"
},
"example-el7-1644251369:33314": {
"address": "example-el7-1644251369:33314",
"applierWorkerThreads": 4,
"fenceSysVars": [],
"instanceErrors": [
"NOTE: instance server_id is not registered in the metadata.
Use cluster.rescan() to update the metadata.",
"NOTE: The required parallel-appliers settings are not enabled on the instance.
Use dba.configureInstance() to fix it."
],
"memberId": "303dcfa7-8926-11ec-a6e5-02001707f44a",
"memberRole": "PRIMARY",
"memberState": "ONLINE",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.28"
},
"example-el7-1644251369:33317": {
"address": "example-el7-1644251369:33317",
"applierWorkerThreads": 4,
"fenceSysVars": [],
"instanceErrors": [
"NOTE: instance server_id is not registered in the metadata.
Use cluster.rescan() to update the metadata.",
"NOTE: The required parallel-appliers settings are not enabled on the instance.
Use dba.configureInstance() to fix it."
],
"memberId": "3bb2592e-8926-11ec-8b6f-02001707f44a",
"memberRole": "PRIMARY",
"memberState": "ONLINE",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.28"
}
},
"topologyMode": "Multi-Primary"
},
"groupInformationSourceMember": "example-el7-1644251369:33311",
"metadataVersion": "2.1.0"
}
<Cluster>.status({extended: true}) 显示有关 InnoDB Cluster 集群的更多详细信息。在此示例中,使用布尔值 true,相当于 <Cluster>.status({'extended':1})。有关更多信息,请参阅 使用 Cluster.status() 检查集群状态。
- 解决
<Cluster>.status({extended:1})操作返回的任何错误。
在此示例中,instanceErrors建议在此升级中,应对InnoDB Cluster集群中的每个成员发出<Cluster>.rescan()和dba.configureInstance():
... "NOTE: instance server_id is not registered in the metadata. Use <Cluster>.rescan() to update the metadata.", "NOTE: The required parallel-appliers settings are not enabled on the instance. Use dba.configureInstance() to fix it." ...
<Cluster>.rescan() 操作使您能够重新扫描 InnoDB Cluster 集群以查找新的和过时的组复制实例,以及拓扑模式的变更。有关更多信息,请参阅 重新扫描集群。
mysqlsh> <Cluster>.rescan();
Rescanning the cluster...
Result of the rescanning operation for the 'MyCluster1' cluster:
{
"name": "MyCluster1",
"newTopologyMode": null,
"newlyDiscoveredInstances": [],
"unavailableInstances": [],
"updatedInstances": []
}
dba.configureInstance() 函数检查实例的所有设置,以使其能够用于 InnoDB Cluster。有关更多信息,请参阅配置实例以供 InnoDB Cluster 使用 。
在此示例中,我们对 InnoDB Cluster 中的每个成员发出 dba.configureInstance(),以确保在实例上启用所需的并行应用(appliers)线程设置:
mysqlsh> dba.configureInstance('cladmin:cladminpw@localhost:33311')
The instance 'example-el7-1644251369:33311' belongs to an InnoDB Cluster.
Configuring local MySQL instance listening at port 33311 for use in an InnoDB cluster...
This instance reports its own address as ^[[1mexample-el7-1644251369:33311^[[0m
Clients and other cluster members will communicate with it through this address by default.
If this is not correct, the report_host MySQL system variable should be changed.
applierWorkerThreads will be set to the default value of 4.
^[[36mNOTE: ^[[0mSome configuration options need to be fixed:
+----------------------------------------+---------------+----------------+----------------------------+
| Variable | Current Value | Required Value | Note |
+----------------------------------------+---------------+----------------+----------------------------+
| binlog_transaction_dependency_tracking | COMMIT_ORDER | WRITESET | Update the server variable |
+----------------------------------------+---------------+----------------+----------------------------+
Configuring instance...
The instance 'example-el7-1644251369:33311' was configured to be used in an InnoDB cluster.
有关 InnoDB Cluster 集群升级故障排除的信息,请参阅 InnoDB Cluster 升级排错。
7.10.2. InnoDB Cluster 升级排错
本章节介绍 InnoDB Cluster 升级过程中的故障排除。
7.10.2.1. Bug #28285389
MySQL Shell 将连接参数中提供的 host 值用作 AdminAPI(如 dba.createCluster() 和 Cluster.addInstance())在元数据中注册实例时的目标主机名。但是,连接参数中的 host 值可能与 Group Replication 使用或报告的 hostname 值不一致。当定义了系统变量 report_host(换句话说,值不为 NULL),Group Replication 则使用该变量的值作为目标主机名,否则使用 hostname 的值作为目标主机名。现在,AdminAPI 采用与 Group Replication 相同的逻辑,在元数据中注册目标实例,并将该目标主机名设置为实例上 group_replication_local_address 变量的默认值,而不是使用 MySQL Shell 连接参数中的 host 值。当 report_host 变量设置为空(empty)时,Group Replication 将用空值作为目标主机名,但 AdminAPI(如 dba.checkInstanceConfiguration()、dba.configureInstance()、dba.createCluster() 等命令)将用报告的 hostname 值作为目标主机名,这与 Group Replication 不一致。如果设置系统变量 report_host 为空(empty),则会生成错误。(Bug #28285389)
对于使用 MySQL Shell < 8.0.16 创建的 InnoDB Cluster 集群,尝试从使用 ≥ 8.0.16 执行的完全中断中重启 InnoDB Cluster 集群会导致此错误(Bug #28285389)。这是由于元数据中的值与实例报告的report_host 或 hostname 的值不匹配造成的。解决方法是:
-
确定“种子(
seed)”实例,即具有最新GTID set集的实例为“种子(seed)”实例。可用dba.rebootClusterFromCompleteOutage()操作检测实例是否为种子,如果当前会话未连接到种子实例,则该操作会生成错误。 -
将
report_host系统变量设置为存储在目标实例的元数据架构(Metadata schema)中的值。该值是创建InnoDB Cluster集群时,实例定义中使用的hostname:port对。该值可以通过实例的mysql_innodb_cluster_metadata.instances表来查阅。
例如,假设使用以下命令序列创建集群:
mysql-js> \c clusterAdmin@localhost:3306
mysql-js> dba.createCluster("myCluster")
因此,存储在元数据中的主机名值为“localhost”,因此,种子实例中的 report_host 必须设置为“localhost”。
-
仅使用种子实例重启集群。在交互式提示处,不要将其余实例添加到
InnoDB Cluster集群中。 -
使用
Cluster.rescan()将其他实例添加回InnoDB Cluster集群。 -
从
InnoDB Cluster集群中删除种子实例。 -
在种子实例上停止
mysqld,并删除report_host设置或将report_host其替换为之前存储在元数据(Metadata schema)中的值。 -
重启种子实例并使用
Cluster.addInstance()将其添加回InnoDB Cluster集群。
这样可以将 InnoDB Cluster 集群顺利、完整地升级到最新的 MySQL Shell 版本。另一种可能性(取决于用例)是简单地设置 InnoDB Cluster 集群所有成员上的 report_host 值,以匹配 InnoDB Cluster 集群创建时在元数据模式(Metadata schema)中注册的值。




