MySQL 8 InnoDB 集群管理

使用 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了,会给出警告信息。

上一篇:正则表达式解析URL


下一篇:Unity sqlite学习笔记一