参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/mysql-innodb-cluster-working-with-cluster.html
检索InnoDB集群
使用dba.createCluster() 创建集群时,该操作将返回可以分配给变量的Cluster对象。 您可以使用此对象来处理群集,例如添加实例或检查群集的状态。 如果要在以后再次检索集群,例如在重新启动MySQL Shell之后,请使用dba.getCluster(name,[options])函数。 例如:
mysql-js> var cluster1 = dba.getCluster()
如果未指定群集名称,则返回默认群集。 如果在MySQL Shell全局会话当前连接的服务器实例的InnoDB集群元数据中存储了多个集群,请指定要检索的集群的名称。
检查InnoDB群集状态
集群对象提供status()方法,使您可以检查集群的运行方式。 在能检查InnoDB集群的状态之前,您需要通过连接到其任何实例来获取对InnoDB集群对象的引用。 但是,如果要更改群集的配置,则必须连接到“R / W”实例。 发布status()会根据您所连接的服务器实例来检索集群的状态,并输出状态报告。
重要
集群中实例的状态直接影响状态报告中提供的信息。 与属于群集的实例相比,离开群集的实例提供了群集的不同视图。 因此,请确保您连接的实例的状态为ONLINE。
有关InnoDB集群如何运行的信息,请使用集群的status()方法:
mysql-js> var cluster = dba.getCluster()
mysql-js> cluster.status()
cluster.status()输出的信息提供以下信息:
- clusterName:在dba.createCluster()期间分配给此集群的名称。
- defaultReplicaSet:属于InnoDB集群并包含数据集的服务器实例。
- primary:仅在群集以单主模式运行时显示。 显示当前主实例的地址。 如果未显示此字段,则群集以多主模式运行。
- ssl:群集是否使用安全连接。 显示REQUIRED或DISABLED的值,具体取决于在createCluster()或addInstance()期间如何配置memberSslMode选项。 此参数返回的值对应于实例上的group_replication_ssl_mode服务器变量的值。
- status:集群的此元素的状态。 对于整个群集,它描述了此群集提供的高可用性。 状态为以下之一:
- ONLINE:实例在线并参与群集。
- OFFLINE:实例已失去与其他实例的连接。
- RECOVERING:实例尝试通过在成为ONLINE成员之前检索所需的事务来尝试与集群同步。
- UNREACHABLE:实例已丢失与群集的通信。
- ERROR:实例在恢复阶段或应用事务时遇到错误。
重要:
实例进入ERROR状态后,super_read_only选项设置为ON。 要退出ERROR状态,必须使用super_read_only = OFF手动配置实例。
- (MISSING):实例的状态,它是已配置群集的一部分,但当前不可用。
注意:MISSING状态是特定于InnoDB集群,它不是Group Replication生成的状态。 MySQL Shell使用此状态来指示在元数据中注册但在实时群集视图中找不到的实例。
- topology:已添加到集群的实例。
- Host name of instance:实例的主机名,例如localhost:3310。
- role:此实例在集群中提供的功能。 目前只有HA,具有高可用性。
- mode:服务器是读写(“R / W”)还是只读(“R / O”)。 模式表示R / W(可读写)或R / O(只读)。 在单主模式下,只有标记为“R / W”的一个实例可以执行数据库的更新事务,因此它是主数据库。 如果该实例由于任何原因(例如意外停止)而无法访问,则剩余的“R / O”实例之一将自动接管其位置并成为新的“R / W”主实例。 在多主模式下,所有实例都标记为“R / W”。
描述InnoDB集群的结构
要获取有关InnoDB集群本身结构的信息,请使用cluster.describe()函数:
mysql-js> cluster.describe(); { "clusterName": "test", "adminType": "local", "defaultReplicaSet": { "name": "default", "instances": [ { "name": "localhost:3310", "host": "localhost:3310", "role": "HA" }, { "name": "localhost:3320", "host": "localhost:3320", "role": "HA" }, { "name": "localhost:3330", "host": "localhost:3330", "role": "HA" } ] } }
此函数的输出显示InnoDB集群的结构,包括其所有配置信息,等等。
Super 只读和实例
每当组复制停止时,super_read_only变量将设置为ON以确保不对该实例进行写入。 当您尝试将这些实例与以下AdminAPI命令一起使用时,您可以选择在实例上设置super_read_only = OFF:
- dba.configureLocalInstance()
- dba.createCluster()
- dba.rebootClusterFromCompleteOutage()
- dba.dropMetadataSchema()
当AdminAPI遇到具有super_read_only = ON的实例时,在交互模式下,您可以选择设置super_read_only = OFF。 例如:
mysql-js> var myCluster = dba.createCluster('testCluster')
A new InnoDB cluster will be created on instance 'ic@ic-1:3306'. The MySQL instance at 'ic@ic-1:3306' 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.
Note: there are open sessions to 'ic@ic-1:3306'. You may want to kill these sessions to prevent them from performing unexpected updates: 1 open session(s) of 'ic@ic-1:3306'.
Do you want to disable super_read_only and continue? [y|N]:
显示实例的当前活动会话数。 您必须确保没有应用程序可能无意中写入实例。 通过回答y确认AdminAPI可以写入实例。 如果列出的实例有多个打开的会话,请在允许AdminAPI设置super_read_only = OFF之前谨慎操作。
要强制该函数在脚本中设置super_read_only = OFF,请将clearReadOnly选项设置为true。 例如dba.configureInstance(instance,{clearReadOnly:true})。
管理 sandbox 实例
sandbox实例运行后,可以使用以下方法随时更改其状态:
- 要停止sandbox实例,请使用dba.stopSandboxInstance(instance)。 与dba.killSandboxInstance(instance)不同,会优雅地停止实例。
- 要启动sandbox实例,请使用dba.startSandboxInstance(instance)。
- 要杀死sandbox实例,请使用dba.killSandboxInstance(instance)。 这样可以在不优雅地停止实例的情况下停止实例,并且可以模拟意外停止。
- 要删除sandbox实例,请使用dba.deleteSandboxInstance(instance)。 这会从文件系统中完全删除sandbox实例。
从InnoDB 集群中移除实例
如果您愿意,可以随时从群集中删除实例。 这可以使用removeInstance()方法完成,如下例所示:
mysql-js> cluster.removeInstance('root@localhost:3310')
自定义 InnoDB 集群
创建集群并向其添加实例时,AdminAPI会自动配置组名,本地地址和种子实例等值。建议大多数部署使用这些默认值,但用户可以通过将以下选项传递给dba.createCluster()和cluster.addInstance()来覆盖这些默认值。
要自定义InnoDB集群创建的复制组的名称,请将groupName选项传递给dba.createCluster()命令。这将设置group_replication_group_name系统变量。该名称必须是有效的UUID。
要自定义为来自其他实例的连接提供的地址,请将localAddress选项传递给dba.createCluster()和cluster.addInstance()命令。以host:port格式指定地址。这将在实例上设置group_replication_local_address系统变量。该地址必须可供集群中的所有实例访问,并且必须仅为内部集群通信保留。换句话说,不要使用此地址与实例进行通信。
要在实例加入群集时自定义作为种子的实例,请将groupSeeds选项传递给dba.createCluster()和cluster.addInstance()命令。 当新实例加入群集并用于向新实例提供数据时,将被关联种子实例。 地址指定为逗号分隔列表,例如host1:port1,host2:port2。 这会配置group_replication_group_seeds系统变量。
有关更多信息,请参阅这些AdminAPI选项配置的系统变量的文档。
重新加入集群
如果实例离开集群,例如 因为它丢失了连接而没有或无法自动重新加入集群,则可能需要在稍后阶段将其重新加入集群。 将实例重新加入集群使用cluster.rejoinInstance()。
如果实例没有持久化它的配置,例如它在被添加到集群时,您没有在实例上本地发出dba.configureLocalInstance(),重新启动时实例不会自动重新加入集群。 解决方案是发出cluster.rejoinInstance(),以便再次将实例添加到集群。 然后连接到实例,在本地运行MySQL Shell并发出dba.configureLocalInstance()。 这可确保InnoDB群集配置持久保存到实例的选项文件,以使其能够自动重新加入群集。
TIP:
如果实例设置的是 super_read_only=ON,则需要确认 AdminAPI能设置 super_read_only=OFF。
从仲裁丢失中恢复群集
如果某个实例(或多个实例)失败,则群集可能会丢失其仲裁,即在新主节点中投票的能力。 在这种情况下,您可以使用cluster.forceQuorumUsingPartitionOf()方法重新建立仲裁,如以下MySQL Shell示例所示:
// open session to a cluster
mysql-js> cluster = dba.getCluster("prodCluster") // The cluster lost its quorum and its status shows // "status": "NO_QUORUM"
mysql-js> cluster.forceQuorumUsingPartitionOf("localhost:3310") Restoring replicaset 'default' from loss of quorum, by using the partition composed of [localhost:3310]
Please provide the password for 'root@localhost:3310': ****** Restoring the InnoDB cluster ...
The InnoDB cluster was successfully restored using the partition from the instance 'root@localhost:3310'.
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.
从大型中断中重新启动群集
如果您的群集遭受完全中断,您可以使用dba.rebootClusterFromCompleteOutage()确保它已正确重新配置。 如果群集已完全停止,则必须启动实例,然后才能启动群集。 例如,如果已重新启动运行sanbox群集的计算机,并且实例位于端口3310,3320和3330,则发出:
mysql-js> dba.startSandboxInstance(3310)
mysql-js> dba.startSandboxInstance(3320)
mysql-js> dba.startSandboxInstance(3330)
这可确保sanbox实例正在运行。 在生产部署的情况下,您必须在MySQL Shell之外启动实例。 实例启动后,连接到实例并运行MySQL Shell。 然后通过发出以下命令重启群集
mysql-js> shell.connect('root@localhost:3310');
mysql-js> var cluster = dba.rebootClusterFromCompleteOutage();
这可确保在完全中断后正确地重新配置群集。 它使用MySQL Shell连接的实例作为新的种子实例,并根据该实例的现有元数据恢复集群。
如果此过程失败,并且群集元数据已严重损坏,则可能需要删除元数据并从头开始再次创建群集。 您可以使用dba.dropMetadataSchema()删除集群元数据。
警告:
dba.dropMetadataSchema()方法只应在无法恢复群集时用作后的手段。 它无法回退。
重新扫描群集
如果在不使用AdminAPI的情况下更改实例的配置,则需要重新扫描群集以更新InnoDB群集元数据。 例如,如果手动将新实例添加到组复制组,则不会根据对群集的此更改来修改InnoDB群集元数据,因为未使用MySQL Shell。 在这种情况下,有必要使用cluster.rescan()重新扫描集群以更新InnoDB集群元数据。
运行命令cluster.rescan()后,将识别出新发现的实例。 系统会提示您根据需要将每个新发现的实例添加到群集中,或者您可以选择忽略它们。
还会报告不再属于群集或不可用的实例。 在这种情况下,系统会提示您删除实例,或者稍后可以尝试使用cluster.rejoin('ic @ ic-4:3306')等命令将其添加回群集。
检查实例状态
cluster.checkInstanceState()函数可用于验证实例上的现有数据会不会阻止它加入集群。 此过程通过验证实例的全局事务标识符(GTID)状态与集群已处理的GTID进行比较来工作。 通过此检查,您可以确定是否可以将已处理事务的实例添加到集群。
以下演示了在运行的MySQL Shell中发布它:
mysql-js> cluster.checkInstanceState('ic@ic-4:3306')
此函数的输出可以是以下之一:
- OK new:实例没有执行任何GTID事务,因此它不能与集群执行的GTID冲突
- OK recoverable:实例已执行GTID,这些GTID与集群种子实例的已执行GTID不冲突
- ERROR diverged:实例已执行GTID,该GTID与集群种子实例的已执行GTID不同
- ERROR lost_transactions:实例被执行的GTID比集群种子实例被执行的GTID多
可以将具有“OK”状态的实例添加到群集,因为该实例上的任何数据都与群集一致。 换句话说,被检查的实例没有执行任何与集群执行的GTID冲突的事务,并且可以恢复到与其余集群实例相同的状态。
解散InnoDB集群
要解散InnoDB集群,您需要连接到读写实例,例如单主集群中的主实例,并使用Cluster.dissolve()命令。 这将删除与群集关联的所有元数据和配置,并禁用实例上的组复制。 不会删除在实例之间复制的任何数据。 无法回退群集的解散,因此必须传递force:true以确认您要解散群集。 例如:要再次创建它,请使用dba.createCluster()。
mysql-js> session
<ClassicSession:root@localhost:3310>
mysql-js> cluster.dissolve({force:true}) The cluster was successfully dissolved. Replication was disabled but user data was left intact.
注意:
发出cluster.dissolve()后,分配给Cluster对象的任何变量都不再有效。
保护您的群集
可以将服务器实例配置为使用安全连接。 有关在MySQL中使用SSL的一般信息,请参见第6.4节“使用加密连接”。 本节介绍如何配置群集以使用SSL。 另一种安全可能性是配置哪些服务器可以访问群集,请参阅创建服务器白名单。
重要:
一旦配置群集以使用SSL后,必须将服务器添加到ipWhitelist。
创建 服务器白名单
使用群集的createCluster(),addInstance()和rejoinInstance()方法时,您可以选择指定属于群集的已批准服务器列表,称为白名单。 通过以这种方式明确指定白名单,您可以提高群集的安全性,让只有白名单中的服务器才能连接到群集。 默认情况下,如果未明确指定,白名单将自动设置为服务器具有网络接口的专用网络地址。 要配置白名单,请在使用该方法时指定要使用ipWhitelist选项添加的服务器。 将服务器作为逗号分隔列表传递,并用引号括起来。 使用ipWhitelist选项在实例上配置group_replication_ip_whitelist系统变量。 例如:
mysql-js> cluster.addInstance("ic@ic-3:3306", {ipWhitelist: "203.0.113.0/24, 198.51.100.110"})
这会将实例配置为仅接受来自地址203.0.113.0/24和198.51.100.110的服务器的连接。 从MySQL 5.7.21开始,白名单还可以包含主机名,只有在其他服务器发出连接请求时才会解析主机名。
警告:
主机名本质上不如白名单中的IP地址安全。 MySQL执行FCrDNS验证,提供良好的保护级别,但可能会受到某些类型的攻击。 仅在严格必要时指定白名单中的主机名,并确保用于名称解析的所有组件(如DNS服务器)都在您的控制之下。 您还可以使用hosts文件在本地实现名称解析,以避免使用外部组件。
使用 MYSQL shell 执行脚本
您可以使用脚本自动执行群集配置。 例如:
shell> mysqlsh -f setup-innodb-cluster.js
注意:
脚本文件名后指定的任何命令行选项都将传递给脚本而不是MySQL Shell。 您可以使用JavaScript中的os.argv数组或Python中的sys.argv数组来访问这些选项。 在这两种情况下,数组中个被获取的选项是脚本名称。
此处显示了示例脚本文件的内容:
print('MySQL InnoDB cluster sandbox set up\n'); print('==================================\n');
print('Setting up a MySQL InnoDB cluster with 3 MySQL Server sandbox instances.\n'); print('The instances will be installed in ~/mysql-sandboxes.\n');
print('They will run on ports 3310, 3320 and 3330.\n\n');
var dbPass = shell.prompt('Please enter a password for the MySQL root account: ', {type:"password"});
try {
print('\nDeploying the sandbox instances.');
dba.deploySandboxInstance(3310, {password: dbPass});
print('.');
dba.deploySandboxInstance(3320, {password: dbPass});
print('.');
dba.deploySandboxInstance(3330, {password: dbPass});
print('.\nSandbox instances deployed successfully.\n\n');
print('Setting up InnoDB cluster...\n');
shell.connect('root@localhost:3310', dbPass);
var cluster = dba.createCluster("prodCluster");
print('Adding instances to the cluster.');
cluster.addInstance({user: "root", host: "localhost", port: 3320, password: dbPass});
print('.'); cluster.addInstance({user: "root", host: "localhost", port: 3330, password: dbPass});
print('.\nInstances successfully added to the cluster.');
print('\nInnoDB cluster deployed successfully.\n'); } catch(e)
{
print('\nThe InnoDB cluster could not be created.\n\nError: ' + + e.message + '\n');
}