使用 dba.checkInstanceConfiguration()
在添加实例到集群中前,使用该方法检查实例配置是否满足InnoDB 集群要求。
使用 dba.configureLocalInstance() 配置实例
在MySQL Server版本不支持持久化功能的实例上,需要使用该方法添加修改配置信息到本地实例的选项文件中。比如下面的更改集群配置的操作:
• dba.configureInstance()
• dba.createCluster()
• Cluster.addInstance()
• Cluster.removeInstance()
• Cluster.rejoinInstance()
使用 dba.getCluster() 接收 InnoDB 集群
dba.createCluster() 返回集群对象。该对象可以赋值给变量。如果后面需要获取已创建集群对象,可以通过该方法。
使用 cluster.describe()
该方法用于获取集群结构信息。
使用 Cluster.status() 检查实例状态
在检查集群状态之前,需要通过连接到集群中的任意实例获取集群对象的引用(reference)。如果需要更改集群对象,需要连接到R/W 实例。
实例状态直接反应集群状态报告提供的信息,因而需要连接到一个在线实例。
扩展信息:cluster.status({'extended':0}) 支持extended扩展操作,可取值包括:0、1、2、3.
监控恢复操作
cluster.status()如果显示为Recovering状态。存在两种恢复方式:克隆、增量。
InnoDB集群和组复制协议
从MySQL 8.0.16版本,组复制有一个通信协议。这个通信协议一般需要显式的管理。因为通信协议的版本要兼容最久组复制成员数据库版本。但是如果是使用AdminAPI管理集群,一般就不需要管理员干预了。AdminAPI会自动根据集群成员版本的变更而自动调整。
检查实例的MySQL版本
MySQL文档给出了三个方法都可以查看实例的MySQL版本,但测试只有cluster.status() 方法可行。
其他两个方法:cluster.describe() 和 cluster.rescan()
super read-only 和 实例
当组复制停止的时候,会将实例设置为 super read only。有三个方法可以修改这个设置,如果再将super_read_only设置为off时,注意是否有应用程序在修改实例。
• dba.configureInstance()
• dba.configureLocalInstance()
• dba.dropMetadataSchema()
注:强制设置super_read_only=off,在方法中添加选项:clearReadOnly.比如:
dba.configureInstance(instance, {clearReadOnly: true})
配置管理InnoDB集群的用户
前面也提到了,在使用dba.configureInstance() 或者 dba.configureLocalInstance() 配置实例时,可以通过clusterAdmin 选项生成一个集群管用户。这也是MySQL推荐的。
也可以通过手工方法配置集群管理用户,赋予适当的权限。如果用户只是用于监控集群可以赋予更少的权限。
配置实例自动重新加入
MySQL 8.0.16 版本开始,支持组复制自动重新加入功能。 在实例从集群中剔除后,自动重新加入集群。AdminAPI 提供autoRejoinTries 选项控制尝试次数。默认情况下,自动重新加入功能没有开启。可以通过下面方法在集群级或者实例级配置该功能。
• dba.createCluster()
• Cluster.addInstance()
• Cluster.setOption()
• Cluster.setInstanceOption()
在网络环境不稳定的集群中,这个参数可以考虑设置。但是如果集群quorum数量的成员丢失了,autoRejoinTries 选项不起作用。
与这个参数相关的另一个参数exitStateActio,在MySQL 8.0.12版本,这个参数可以设置为READ_ONLY,即在实例异常从集群中离开后的动作。在MySQL 8.0.18版本,这个参数可以设置为OFFLINE_MODE。这个模式是比较推荐的,因为如果是READ_ONLY,客户端应用程序可能从该实例读取旧的数据。exitStateActio 选项起作用是在尝试完autoRejoinTries 选项配置的次数后而没有加入到集群中的话。
如果实例正在重新加入集群,下面的操作可能受影响:
• Cluster.status()
• dba.getCluster()
• Cluster.rejoinInstance()
• Cluster.addInstance()
• Cluster.removeInstance()
• Cluster.rescan()
• Cluster.checkInstanceState()
注:Cluster.removeInstance() 如果发生在正在重新加入集群,操作失败,除非指定froce:true 选项。
从InnoDB集群中删除实例
Cluster.removeInstance(instance) 方法可以从集群中删除实例。这个方法确保从集群在线的实例中删除该实例的元数据,以及该实例本身的存储的元数据。
MySQL Shell dba.gtidWaitTimeout 选项控制如果在删除实例时有GTID事务正在应用的等待时间。如果超时,删除操作失败。如果指定force 选项会删除实例。
force 选项一般不应该使用,除非实例不可达,或者不可处理。如果指定force可能导致删除的实例不能重新加入到集群中。
在删除时,可以指定interactive 选项,交互式的删除实例,在实例不可达(unreachable)时,提示是否继续。
重新加入集群
如果实例离开集群,比如丢失连接,并且没有自动重新加入集群。可以通过cluster.rejoinInstance() 方法将实例重新加入到集群中。如果实例 super_read_only=on,传递给这个方法的URI-Like要有权限设置super_read_only=off。
一种可能的情况就是实例加入集群时,没有持久化配置,导致重启后不能自动加入集群。在MySQL 8.0.17,支持PERSIST 命令后这个问题基本不存在了。如果是之前的版本,可以通过这个方法重新加入到集群中,同时注意配置的持久化。
如果实例离开集群后,做了一些操作,比如还原备份,导致实例Server UUID不同了。可能导致实例不能加入集群。因为集群中Server UUID标识实例。可以通过下面的方法处理:
cluster.removeInstance("root@instanceWithOldUUID:3306", {force: true})
cluster.rescan()
注:使用cluster.removeInstance() 方法时,必须指定force 选项,因为从集群角度,实例已经不可达了(unreachable)。先从集群中删除旧的配置信息。通过cluster.rescan() 方法将实例添加到集群元数据中。
定制InnoDB 集群
当创建集群、添加实例到集群的时候,组名、本地地址、seed 实例都由AdminAPI自动配置,这在绝大部分情况下都是推荐的。MySQL也给出了自定义这些选项的方法。在dba.createCluster()或者cluster.addInstance()时传递指定的选项即可。
dba.createCluster()命令传递groupName 选项配置集群组名,对应于组复制的变量:group_replication_group_name。这个值必须要是一个有效的Server UUID。如果看过组复制那一章节,很多时候会把集群中不同实例组名设置为各自的Server UUID。这种做法是不对的。
在dba.createCluster()或者cluster.addInstance()方法中,定制实例用于集群成员通信的本地地址:localAdress 选项。对应于组复制的 group_replication_local_address 系统变量。这个地址:localAdress:port 用于集群成员内部通信。不能使用这个地址连接实例。
默认是主机名:实例端口 * 10 + 1
注意这个地址:端口在集群中所有成员可以访问。
在dba.createCluster()或者cluster.addInstance()方法中,定制seed 实例,使用选项:groupSeeds选项。对应组复制系统变量:group_replication_group_seeds。
seed 实例是在添加实例到集群中时,用于给新增的成员作为数据源。
更改集群拓扑
从MySQL 8.0.15开始,支持在线更改集群拓扑。之前的版本需要先解除集群,重建集群。
Cluster.setPrimaryInstance(instance) 方法在线设置 primary 实例。
通过AdminAPI命令在线修改集群拓扑:
switchToMultiPrimaryMode() 方法切换为多 primary 模式。
注:在切换为多 primary 模式后,6447端口(默认只读)接收读写,并且可通过该端口访问所有集群成员。而6446端口(默认读写)只能连接到其中一个成员(之前是 primary 成员)。
Cluster.switchToSinglePrimaryMode([instance]) 方法切换到单 primary 模式。
设置InnoDB 集群选项
cluster.options() 方法查看当前集群、实例选项设置。添加 all 选项可以查看组复制系统变量设置。
Cluster.setOption(option, value) 方法设置集群、集群所有实例。
Cluster.setInstanceOption(instance, option, value) 方法设置单独的集群实例。
集群和实例级选项:
• exitStateAction
• memberWeight
仅实例级:
• label
仅集群级:
• consistency
• expelTimeout
• clusterName
检查实例状态
cluster.checkInstanceState() 方法检查实例上已存在的数据。通过对比实例上GTID与集群中的GTID作比较。这里会涉及到实例添加到集群时,如果做恢复操作。配合dba.checkInstanceConfiguration() 方法。
创建服务器白名单
dba.createCluster() 或者 cluster.addInstance() ,ipWhitelist 选项配置白名单,对应于组复制的group_replication_ip_whitelist 系统变量。
配置故障转移一致性
从MySQL 8.0.14版本开始支持使用AdminAPI命令的 consistency 选项。在调用createCluster() 方法时,可以指定一致性选项。默认值是:EVENTUAL。对应于组复制的group_replication_consistency 系统变量。这个值在单 primary 选 primary 时,可能导致客户端应用程序读取旧的(stable)数据。推荐值是:consistency=1 对应于BEFORE_ON_PRIMARY_FAILOVER。
配置选举过程
在single primary 模式下,在 primary 故障,集群选 primary 时,默认是通过优先通过 memberWeight 选项,对应于组复制的 group_replication_member_weight 系统变量。如果成员权重相同,对比Server UUID。
可以通过指定memberWeight 选项,这样在做primary 选举时优先选择。
AdminAPI 脚本
MySQL Shell支持脚本配置、管理集群。比如:
shell> mysqlsh -f setup-innodb-cluster.js
注:脚本名称后的选项是传给给脚本的。可以通过JS中的os.argv 或者 Python 中的 sys.argv 传递参数。
解散 InnoDB 集群
Cluster.dissolve() 提供了解散现有集群的方法。删除元数据和集群配置。但保留集群成员之间复制的数据。
如果有集群实例不可达,先考虑将其加入集群中,然后再解散集群,保证集群成员的一致性。
MySQL Shell 选项:dba.gtidWaitTimeout 指定解散集群时允许处理的GTID时间。超时导致解散操作失败,可以通过指定force:true强制解散集群。
恢复丢失Quorum的集群
Cluster.forceQuorumUsingPartitionOf(instance) 方法用于恢复集群中majority 实例丢失。这个方法具有一定的危险性,可能认为产生脑裂问题。给该方法传递一个在线实例,通过读取该实例的元数据,恢复集群。
重启集群
dba.rebootClusterFromCompleteOutage() 方法用于在集群完全断电后重新配置集群。使用这个方法前先确认集群成员是否启动,连接到集群中GTID 超集的实例。在交互模型下,对于发现的实例,MySQL Shell提示是否加入集群;对于不可达的实例,MySQL Shell提示是否从集群中删除实例。如果不是运行在交互模式下,可以通过cluster.rejoinInstance() 和 cluster.removeInstance() 实现类似功能选项。
如果dba.rebootClusterFromCompleteOutage() 方法失败,可以通过dba.dropMetadataSchema() 方法删除集群元数据,然后dba.createCluster() 重建集群。
RESCAN 集群
如果使用非AdminAPI命令更改集群配置,比如:手工更改实例配置以解决配置问题或者实例丢失连接。可以通过cluster.rescan()方法更新InnoDB元数据以匹配当前实力配置。
InnoDB集群和Auto-Increment
在InnoDB集群中使用实例时,为避免多 primary 集群模式下自增长碰撞(collisions),InnoDB集群自动根据集群模式以及实例数量配置 auto_increment_increment 和 auto_increment_offset 系统变量。
单 primary 模式下,设置auto_increment_increment=1 和 auto_increment_offset=2。
多 primary 模式下配置:
If the group is running in multi-primary mode, then when the cluster has 7 instances or less set auto_increment_increment to 7 and auto_increment_offset to 1 + server_id % 7. If a multiprimary cluster has 8 or more instances set auto_increment_increment to the number of instances and auto_increment_offset to 1 + server_id % the number of instances.
保护集群
可以配置服务器使用安全连接。
创建的集群使用了SSL,则必须将服务器加入到ipWhitelist中。
dba.createCluster() 创建集群时,如果seed 实例支持SSL连接。则创建的集群支持SSL。通过cluster.addInstance() 方法添加的实例也需要支持SSL。
memberSslMode 选项支持三个可选值:AUTO(默认)、REQUIRED、DISABLED.
通过组复制adoptFromGR方法生成的集群,没有SSL设置选项。集群的SSL配置根据组复制设置而定。
MySQL Router 和 元数据服务器
如果在MySQL Router bootstrap 集群后,集群添加实例,需要MySQL Router 重新 bootstrap 更新服务器记录的实例地址列表。
可以bootstrap 多个 MySQL Router,信息会记录在元数据中。从MySQL 8.0.19 版本开始,cluster.listRouters() 方法可以查看元数据中注册的MySQL Router列表。
MySQL 8.0.19 版本,提供方法:Cluster.removeRouterMetadata(router) 从元数据中删除MySQL Router信息。
MySQL 克隆和InnoDB 集群
添加实例到集群中,可能存在一个分布式恢复的过程:实例同步集群中的数据。之前只有一种方法:增量恢复,也就是异步复制技术。存在一个问题:如果实例需要复制的GTID事务已经PURGED,即@@gtid_purged > 0。实例所需要的事务不能在二进制日志中完全找到。这样情况类似做MySQL 主从复制,解决的方法是利用最近的备份先恢复到实例(Slave)中。再利用复制技术同步二进制日志。
MySQL 8.0.17 版本对于这种情况提供了方便的解决方案:MySQL 克隆技术。克隆技术也是在集群中的donor(数据发送者)做数据快照,这个集群在使用cluster.addInstance() 方法添加实例时会自动判断是否需要通过克隆来做分布式恢复。cluster.addInstance() 方法提供了3个可选值:auto(默认)、clone、incremental。
注:如果实例是通过克隆技术完成加入集群的。在克隆操作时会将实例之前的数据清除,所有没有保存在表中的MySQL设置保存。在cluster.status() 方法中也会提供额外信息。
即使donor 实例的GTID_EXECUTED=0,也不能说明donor instance 二进制日志包含所有的事务,因为有可能donor server 之前运行时并没有启用GTID。因为简单地使用 recoveryMethod 选项值:incremental 不是合理的。
recoveryMethod 默认值:auto。集群会确定在交互模式下,使用什么方法添加实例是合理的。如果是非交互模式,恢复方法需要显示的设置。
recoveryMethod 可选值的一些说明:
clone:如果准备加入进群的实例不好数据,或者数据可丢弃。可以使用clone方式。这种方式下,MySQL Clone 插件自动安装,恢复账号自动创建。
incremental:使用异步复制做增量恢复。这种情况发生在:确定所有事务使用GTID,待加入实例包含集群所有GTID或者子集。
如果增量恢复与克隆技术都可以使用的话,MySQL 推荐使用克隆技术,这种做法一般会比较快的恢复事务,而且可以清除实例上不需要的数据。
Cluster.checkInstanceState() 与 MySQL Clone
dba.checkInstanceConfiguration() 和 Cluster.checkInstanceState() :前者验证实例配置,后者验证实例数据。
使用Cluster.checkInstanceState() 方法可以验证如果donor instances 如果GTID_PURGED <> 0,而clone方法可用时,会给出建议。如果克隆方法不可用,会给出实例不可恢复警告。
dba.checkInstanceConfiguration() 和 MySQL Clone
如果dba.checkInstanceConfiguration() 发现MySQL Clone 可用,但是被disable了,会给出警告信息。