网络分区
# 这里说的成员标识符为每个组成员自身数据库Server的UUID
为了理解这种类型的网络分区,下文中将描述一个场景,在这个场景中,最初有5个成员在线(在一起正确地工作),而当只有2个组成员在线时(S1和S2在线,S3、S4、S5三个成员失联),组将发生变化。该场景如上图的Majority Lost部分所示。一开始,这个组运行状态良好,成员之间通讯正常。通过performance_schema.replication_group_members表可以查看到各个组成员的状态,如下:
S1:199b2df7-4aaf-11e6-bb16-28b2bd168d07
S2:199bb88e-4aaf-11e6-babe-28b2bd168d07
S3:1999b9fb-4aaf-11e6-bb54-28b2bd168d07
S4:19ab72fc-4aaf-11e6-bb51-28b2bd168d07
S5:19b33846-4aaf-11e6-ba81-28b2bd168d07
# 任意登录到一个在线的成员执行查询即可,假设这里从S1成员上查看
当成员S3、S4、S5意外失联几秒种后,再次查看S1上的performance_schema.replication_group_members表,会发现S1和S2仍然处于ONLINE状态,但是成员S3、S4、S5处于UNREACHABLE状态(如下所示)。此时,组由于与大多数成员失联,导致系统无法重新配置自己来调整新的组成员资格。
mysql> SELECT MEMBER_ID,MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+-------------+
| MEMBER_ID | MEMBER_STATE |-MEMBER_ROLE |
+--------------------------------------+--------------+-------------+
| 1999b9fb-4aaf-11e6-bb54-28b2bd168d07 | ONLINE | SECONDARY |
| 199b2df7-4aaf-11e6-bb16-28b2bd168d07 | ONLINE | PRIMARY |
| 199bb88e-4aaf-11e6-babe-28b2bd168d07 | ONLINE | SECONDARY |
| 19ab72fc-4aaf-11e6-bb51-28b2bd168d07 | ONLINE | SECONDARY |
| 19b33846-4aaf-11e6-ba81-28b2bd168d07 | ONLINE | SECONDARY |
+--------------------------------------+--------------+-------------+
mysql> SELECT MEMBER_ID,MEMBER_STATE FROM performance_schema.replication_group_members;
从performance_schema.replication_group_members表中的信息可以看出,此时组在没有外部干预的情况下无法继续对外提供服务,因为此时大多数成员不可访问,组变为只读,需要重置组成员资格列表对系统进行恢复。在重置组成员资格之前,建议先收集S3、S4、S5中的相关的日志,以便后续排查。然后,停止S1和S2上的组复制,然后,针对S1和S2两个组成员重新启动组复制,等待 S3、S4、S5 恢复正常之后,可以陆续将其加入到组中。疏通分区
+--------------------------------------+--------------+
| MEMBER_ID | MEMBER_STATE |
+--------------------------------------+--------------+
| 1999b9fb-4aaf-11e6-bb54-28b2bd168d07 | UNREACHABLE |
| 199b2df7-4aaf-11e6-bb16-28b2bd168d07 | ONLINE |
| 199bb88e-4aaf-11e6-babe-28b2bd168d07 | ONLINE |
| 19ab72fc-4aaf-11e6-bb51-28b2bd168d07 | UNREACHABLE |
| 19b33846-4aaf-11e6-ba81-28b2bd168d07 | UNREACHABLE |
+--------------------------------------+--------------+
mysql> SELECT @@group_replication_local_address;
假设通过上述语句,查看到S1的组通信地址为127.0.0.1:10000,S2的组通信地址为127.0.0.1:10001,然后,就可以通过系统变量group_replication_local_address,在S1和S2中任意一个成员上执行如下语句,以注入一个新的组成员资格配置,从而覆盖已经失去的仲裁能力的现有组成员资格配置。
# 这里假设登录到S1中执行
执行上述语句之后,通过强制不同的组成员资格配置来解除组的阻塞状态。此时,再次登录S1、S2中,查看performance_schema.replication_group_members表。
mysql> SET GLOBAL group_replication_force_members="127.0.0.1:10000,127.0.0.1:10001";
# 在S1中查看,发现只剩下S1和S2两个成员,且都处于ONLINE状态
在强制执行新的组成员资格配置时,需要确保被强制驱逐的所有组成员是否都被驱逐成功,然后将其停止。因为,在上面描述的场景中,如果S3、S4、S5并不是真的不可访问,而是处于ONLINE状态,则,在针对S1和S2执行强制重新配置组成员资格配置时,剩余的S3、S4、S5成员由于它们3个占原组5成员资格数量的多数,它们3个会通过仲裁能力形成新的组成员资格配置。在这种情况下,强制使用S1和S2的组成员资格列表配置新组,可能会造成人为的裂脑情况。因此,在强制执行新组成员资格配置之前,务必确保将被驱逐的成员发生故障问题的真实性,并将其关闭(关闭数据库进程)。
mysql> SELECT MEMBER_ID,MEMBER_STATE FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+
| MEMBER_ID | MEMBER_STATE |
+--------------------------------------+--------------+
| b5ffe505-4ab6-11e6-b04b-28b2bd168d07 | ONLINE |
| b60907e7-4ab6-11e6-afb7-28b2bd168d07 | ONLINE |
+--------------------------------------+--------------+
# 在S2中查看,发现只剩下S1和S2两个成员,且都处于ONLINE状态
mysql> SELECT * FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+
| MEMBER_ID | MEMBER_STATE |
+--------------------------------------+--------------+
| b5ffe505-4ab6-11e6-b04b-28b2bd168d07 | ONLINE |
| b60907e7-4ab6-11e6-afb7-28b2bd168d07 | ONLINE |
+--------------------------------------+--------------+
在使用系统变量group_replication_force_members成功强制创建新的组成员资格并解除组阻塞之后,需要将该变量的值清空,否则无法执行START GROUP_REPLICATION语句(系统变量group_replication_force_members必须为空时,START GROUP_REPLICATION语句才能执行)。
配置支持IPv6和混合IPv6与IPv4地址的组
从MySQL 8.0.14开始,组成员可以使用IPv6地址替代VPv4地址进行组内通信。要正确使用IPv6地址,需要在各个组成员的主机操作系统和MySQL Server上都配置为支持IPv6。有关为设置IPv6支持的详细说明,请参考链接:https://dev.mysql.com/doc/refman/8.0/en/ipv6-support.htmlgroup_replication_local_address= "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:33061"
# Server A启用系统变量group_replication_bootstrap_group,表示用它来引导组
group_replication_bootstrap_group=on
group_replication_local_address= "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:33061"
# 它在系统变量group_replication_group_seeds中公布了IPv6地址
group_replication_group_seeds= "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:33061"
Server B是joiner节点,假设它的组复制配置设置如下:
# Server B关闭系统变量group_replication_bootstrap_group,表示它不需要引导组,只需要向系统变量
group_replication_group_seeds指定的种子成员请求加入组即可
group_replication_bootstrap_group=off
# 它有一个IPv4组复制本地地址
group_replication_local_address= "203.0.113.21:33061"
group_replication_group_seeds= "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:33061"
假设Server B有一个备选的IPv6地址2001:db8:8b0:40:3d9c:cc43:e006:19e8。为确保Server B成功加入这个组,它的IPv4本地地址和备用的IPv6本地地址都必须在Server A的白名单中列出,如下所示:
# 作为组复制 IP白名单的最佳实践,Server B(和所有其他组成员)应该与Server A具有相同的白名单配置,除非有特殊的安全需求,否则建议保持一致
group_replication_ip_whitelist="203.0.113.0/24,2001:db8:85a3:8d3:1319:8a2e:370:7348, 2001:db8:8b0:40:3d9c:cc43:e006:19e8"
如果组中存在任何一个成员或所有的现有成员使用的是不支持IPV6地址的老MySQL Server版本,则joiner节点不能使用IPV6地址作为本地地址加入组,这适用于如下两种情况。
组中至少一个现有成员使用了IPv6地址,但是一个不支持IPV6地址的Server正在申请加入组。
组中至少有一个现有成员不支持IPV6地址,但是joiner节点使用了IPV6地址。
PS:
如果要使用IPV6地址,请先将不支持IPV6地址的Server版本升级到支持IPV6的Server版本,然后,将所有组成员的系统变量group_replication_local_address的值设置为IPV6地址,或者配置您的DNS以解析IPv6地址。注意:修改系统变量group_replication_local_address的值需要重启组复制才会生效。
通常情况下,建议组中使用同一种通讯协议地址,例如,都使用IPV4或者都使用IPV6,不要混合使用,除非必须(例如:在滚动升级期间的一种折中)。
《千金良方——MySQL性能优化金字塔法则》作者之一。熟悉MySQL体系结构,擅长数据库的整体调优,喜好专研开源技术,并热衷于开源技术的推广,在线上线下做过多次公开的数据库专题分享,发表过近100篇数据库相关的研究文章。
全文完。
Enjoy MySQL 8.0 :)
叶老师的「MySQL核心优化」大课已升级到MySQL 8.0,扫码开启MySQL 8.0修行之旅吧