集群 MGR 故障监控规则
目前,集群在添加 sqlnode 节点和 datanode 节点过程中,会持久化如下 MGR 的系统变量,用户故障的处理:
- group_replication_start_on_boot: ON,重启后自动尝试加入 MGR 集群。
- group_replication_autorejoin_tries: 2016,在 MySQL 服务没有停止的情况下,出现故障时,会自动尝试加入集群,尝试次数为 2016 次,每次失败后,会间隔 5 分钟进行下一次尝试。总的尝试时间大概为 7 天。
- group_replication_unreachable_majority_timeout: 30,默认情况下,如果多数节点同时故障(或者网络分区),剩余的少数节点会一直保持 ONLINE 状态,影响系统使用。集群将该值设置为 30 s的时间,超过该时间后,该节点状态会变成 ERROR 状态。如果是因为网络故障,网络恢复后,故障的节点通过 group_replication_autorejoin_tries 配置,会再次加入集群。
- group_replication_member_expel_timeout: 5s,保持默认值为 5 秒。如果一个节点出现故障,
5-10s后,其它正常节点会将节点自动踢出 MGR 集群。
通过上述规则,无论 sqlnode 节点和 datanode 节点,如果故障时,存在多数节点可用,则:
- 非 MySQL 服务宕机的情况下,故障节点能够自动尝试加入集群,尝试的时间最多为 7 天。由于每次尝试间隔时间为 5 分钟,当故障恢复时,可能节点不一定能马上恢复,最长可能需要5分钟以上的时间。
- MySQL 服务宕机的情况下,重启后,节点会自动尝试加入集群。此时不能存在其它故障,如果失败,则无法自动加入集群。
MGR 主节点切换
在单主模式下(datanode节点为单主),如果 MGR 中的主节点发生故障,5-10s后,MGR 集群会自动选出新主并切换。
注意:当前 MGR 的选主逻辑可能存在一些问题,比如 3 个节点的 MGR,主节点为 A,其它节点为 B,C。A 故障时,假设 B,C均接收到了最新数据,但 B 回放的 gtid 为 100,C 回放的 gtid 为 200,MGR 仍可以选主 B 为新主。此时 B需要将所有的 relaylog 回放完成才能提供服务,会造成集群一段时间不可用。
在多主模式下,不涉及选主问题。
SQLNODE 节点 MGR 监控规则
在 MGR 本身配置基础上,sqlnode 节点会主动监听 MGR 节点的状态变化,并及时更新 SQLNODE 节点集群变化。用户可以通过查询 information_schema.greatdb_sqlnodes 查询 sqlnode 节点的实时状态信息。
DATANODE 节点 MGR 监控规则
在 sqlnode 节点上,会定期(每隔 2s)查看后端 datanode 节点的 MGR 状态,并更新相应的节点状态。用户可以通过查询information_schema.greatdb_datanodes 查询 datanode 节点的状态信息。该状态信息会存在短暂的时延(几秒的时延范围)。
另外,如果一个 shard 中所有的 datanode 节点都因为故障退出了 MGR 集群,但所有的 datanode 节点的 MySQL 服务都已经启动并可以正常连接访问,此时 sqlnode 会尝试自动重建该 shard 的 MGR 集群。
插件安装问题
安装成功的错误日志问题
执行如下 SQL 语句,安装组复制插件。
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
插件安装成功时,在 MySQL 的错误日志中,可能会写入如下日志:
[ERROR] [MY-011685] [Repl] Plugin group_replication reported: 'The group name option is mandatory'
[ERROR] [MY-011660] [Repl] Plugin group_replication reported: 'Unable to start Group Replication on boot'
处理方案:
- 忽略该错误日志。
- 配置文件中,指定参数
loose-group_replication_start_on_boot= OFF
启动失败问题
参数配置问题
没有配置
group_replication_group_name变量mysql> start group_replication; ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log.执行启动命令,并没有详细的错误信息,根据提示,查看错误日志,有如下信息,表示
group_replication_group_name变量没有配置。[ERROR] [MY-011685] [Repl] Plugin group_replication reported: 'The group name option is mandatory'注意:在组复制集群中,同一个复制组的所有节点,都需要配置该参数,且所有节点的配置保持一致。该参数的格式同 server_uuid ,但不能和任何节点的 server_uuid 一样。
没有配置
group_replication_local_address变量mysql> start group_replication; ERROR 3096 (HY000): The START GROUP_REPLICATION command failed as there was an error when initializing the group communication layer.执行启动命令,同样没有提示关键的错误信息。此时,同样查看错误日志,会发现如下错误信息,其中最关键的是第一行的错误,表示
group_replication_local_address参数没有正确配置。[ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] Invalid hostname or IP address () assigned to the parameter local_node!' [ERROR] [MY-011674] [Repl] Plugin group_replication reported: 'Unable to initialize the group communication engine' [ERROR] [MY-011637] [Repl] Plugin group_replication reported: 'Error on group communication engine initialization' [Note] [MY-011649] [Repl] Plugin group_replication reported: 'Requesting to leave the group despite of not being a member' [ERROR] [MY-011718] [Repl] Plugin group_replication reported: 'Error calling group communication interfaces while trying to leave the group'注意:在组复制集群中,每个节点需要单独配置 group_replication_local_address,该参数为 hostname/ip 和 port 的组合,其中 port 为组复制的端口号,而不是 mysql 服务进程的端口号。参数的格式为
[ipv6]:port,或者ipv4:port或者hostname:port。其中,hostname/ip需要能够被集群其它节点正常访问。没有配置 group_replication_group_seeds 参数
mysql> start group_replication; ERROR 3097 (HY000): The START GROUP_REPLICATION command failed as there was an error when joining the communication group.执行启动命令,提示无法加入复制组,但没有更具体的错误提示。此时,同样查看错误日志,有如下信息,其中关键的为第一行,
perrs not configured,表示没有配置group_replication_group_seeds参数。[ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] Unable to join the group: peers not configured. ' [ERROR] [MY-011639] [Repl] Plugin group_replication reported: 'Error on group communication engine start' [Note] [MY-011649] [Repl] Plugin group_replication reported: 'Requesting to leave the group despite of not being a member' [ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] The member is leaving a group without being on one.'注意:该参数格式为多个
group_replication_local_address的组合,使用逗号分隔。一般配置时,需要将所有包含所有节点的group_replication_local_address值。
集群初始化及脑裂问题
当初始化组复制集群时,对于第一个节点,需要将参数 group_replication_bootstrap_group 设置为 ON,否则会报错。
mysql> start group_replication;
ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log.
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> start group_replication;
Query OK, 0 rows affected (3.09 sec)
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)
group_replication_bootstrap_group参数的作用是标记是不是初始化组复制集群,如果设置为 ON,则将以执行节点初始化一个全新的组复制集群。否则,如果设置为 OFF (默认值),该节点将尝试去加入到一个现有的组复制集群中。在上述示例中,因为无法连接到 33061,33062 的组复制端口,所以节点无法加入到一个现有组复制集群中(因为这样的集群不存在),所以启动失败。
[ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] Error on opening a connection to 127.0.0.1:33061 on local port: 33060.'
[ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] Error on opening a connection to 127.0.0.1:33062 on local port: 33060.'
[ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] Error connecting to all peers. Member join failed. Local port: 33060'
[ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] The member was unable to join the group. Local port: 33060'
[ERROR] [MY-011640] [Repl] Plugin group_replication reported: 'Timeout on wait for view after joining group'
[Note] [MY-011649] [Repl] Plugin group_replication reported: 'Requesting to leave the group despite of not being a member'
[ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] The member is leaving a group without being on one.'
注意:当初始化节点启动组复制成功后,因立即将参数 group_replication_bootstrap_group 设置为 OFF。非初始化节点禁止设置参数为ON,否则会导致集群脑裂问题。如下示例可以看出,在相同的配置下,13000,和13001两个mysql并没有出现在同一个组复制集群下。此时,可以认为是出现了脑裂的问题。因此,一定要注意 group_replication_bootstrap_group 参数的配置问题。
connect 13000:
mysql> set global group_replication_group_name='11223344-1122-1122-1122-112233445566';
Query OK, 0 rows affected (0.00 sec)
mysql> set global group_replication_local_address='127.0.0.1:33060';
Query OK, 0 rows affected (0.00 sec)
mysql> set global group_replication_group_seeds='127.0.0.1:33060,127.0.0.1:33061,127.0.0.1:33062';
Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> start group_replication;
Query OK, 0 rows affected (3.09 sec)
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)
connect 13001:
mysql> set global group_replication_group_name='11223344-1122-1122-1122-112233445566';
Query OK, 0 rows affected (0.00 sec)
mysql> set global group_replication_local_address='127.0.0.1:33061';
Query OK, 0 rows affected (0.00 sec)
mysql> set global group_replication_group_seeds='127.0.0.1:33060,127.0.0.1:33061,127.0.0.1:33062';
Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> start group_replication;
Query OK, 0 rows affected (3.27 sec)
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)
+-------------+-------------+--------------+-------------+
| MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE |
+-------------+-------------+--------------+-------------+
| 127.0.0.1 | 13001 | ONLINE | PRIMARY |
+-------------+-------------+--------------+-------------+
1 row in set (0.02 sec)
重新 connect 13000:
mysql> SELECT MEMBER_HOST,MEMBER_PORT,MEMBER_STATE,MEMBER_ROLE FROM performance_schema.replication_group_members;
+-------------+-------------+--------------+-------------+
| MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE |
+-------------+-------------+--------------+-------------+
| 127.0.0.1 | 13000 | ONLINE | PRIMARY |
+-------------+-------------+--------------+-------------+
1 row in set (0.00 sec)
当出现脑裂问题时,会导致数据的异常行为,避免脑裂问题的关键是需要保证 group_replication_bootstrap_group 参数在初始化集群后处于 OFF 状态。
RECOVING 状态问题
- 初始化节点也可能处于 RECOVING 状态,属于正常状态,其余节点需要等待初始节点处于 ONLINE 状态后,才能加入集群
启动组复制集群前,需要在所有节点上执行如下命令,初始化组复制通道。并保证所有的节点需要使用统一的用户名和密码。
CHANGE MASTER TO MASTER_USER="my_user", MASTER_PASSWORD="my_password," FOR CHANNEL "group_replication_recovery"如果没有执行该语句,新加入的节点将长期处于 RECOVING 状态, 如下示例。
mysql> start group_replication; Query OK, 0 rows affected (4.21 sec) mysql> do sleep(30); Query OK, 0 rows affected (30.00 sec) mysql> SELECT MEMBER_HOST,MEMBER_PORT,MEMBER_STATE,MEMBER_ROLE FROM performance_schema.replication_group_members; +-------------+-------------+--------------+-------------+ | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | +-------------+-------------+--------------+-------------+ | 127.0.0.1 | 13000 | ONLINE | PRIMARY | | 127.0.0.1 | 13001 | RECOVERING | SECONDARY | +-------------+-------------+--------------+-------------+ 2 rows in set (0.00 sec)查看错误日志,有如下错误信息,提示错误的组复制通过的用户。
[ERROR] [MY-013117] [Repl] Slave I/O for channel 'group_replication_recovery': Fatal error: Invalid (empty) username when attempting to connect to the master server. Con nection attempt terminated. Error_code: MY-013117- 如果组复制集群中写入了大量的事务,新节点加入集群后,也可能长时间处于 RECOVING 状态,此时,新节点可能是在同步事务。因此,无法根据长时间处于 RECOVING 状态判断节点是否异常,此时可以查看错误日志进行判断。
无法加入集群问题
节点数据不一致。
如果新节点中存在一个事务,该事务在现有的组复制集群中并不存在,则新节点无法加入集群。如下示例:
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY); Query OK, 0 rows affected (0.10 sec) mysql> start group_replication; ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log.查看错误日志,有如下错误信息。
[ERROR] [MY-011526] [Repl] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: 286 2657a7b1-fe43-11ea-ad01-ec5c6826bca3:1 > Group transactions: 11223344-1122-1122-1122-112233445566:1-5' [ERROR] [MY-011522] [Repl] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'无法连接到集群其它节点。
前文中介绍了,集群启动时需要配置参数
group_replication_group_seeds参数。如果节点无法连接到 seeds 中的其它节点,则无法加入集群。此时,需要根据错误日志进行具体分析,可能原因包括:
- group_replication_group_seeds 参数配置错误
- group_replication_local_address 配置错误
- group_replication_group_name 配置错误
- 节点网络异常,网络分区等
- 组复制尚未初始化
- 组复制其它节点发生异常,或者已经退出了组复制
其它异常
此时需要根据具体的原因进行相应的分析和处理。
集群规模退化问题
根据组复制本身的设计原则,如果节点中少数节点发生故障,一段时间后,节点会被踢出集群。此时组复制集群规模自动退化,这属于正常行为,不需要处理。如果需要将故障的节点重新加入集群,再修复故障后,再次执行 START GROUP_REPLICATION 命令即可。
集群规模退化和参数 group_replication_member_expel_timeout 相关,当一个节点故障时,在 expel_timeout 超时时间后,才会主动将该节点踢出集群,实现集群规模的退化。
!!!注意:在该参数超时之前,故障的节点无法通过 START GROUP_REPLICATION 命令重新加入集群,因为节点仍在集群中,所以该参数不宜设置过大,否则会导致节点长时间无法重新加入集群的问题。另外一个问题,当有节点故障时,整个组复制集群的性能吞吐会有较大程度的下降,所以在 expel_timeout 超时之前的时间内,集群性能会急剧下降。
异常及恢复问题
单个节点异常及恢复
可能包含如下情形:
- 单个节点网络异常
- 网络分区
- 节点 mysql 服务进程异常
- 其它异常
恢复方案有:
- 配置参数
group_replication_autorejoin_tries,在网络异常,或者网络分区恢复后,节点会自动尝试重新加入集群。该参数最大值为 2016,代表最多尝试 2016 次,每次间隔 5 分钟,也就是最大尝试时间为 2016 * 5min = 168h = 7d,即最大尝试恢复时间大概在1周左右。 - 配置参数
group_replication_start_on_boot,如果是 mysql 服务进程退出,当参数为 ON 时,重启阶段会自动尝试加入集群。 - 手动执行
START GROUP_REPLICATION命令
这里最需要注意的是 group_replication_start_on_boot,只会在 mysql 服务进程重启的时候自动尝试加入集群,并且不受参数 group_replication_autorejoin_tries 参数控制。如果重启后因其它原因导致加入集群失败,则不会继续自动尝试了,此时需要进行手动恢复。
多数节点同时故障的问题
可能包含的原因有:
- 集群节点数量为 2n,网络分区导致每个分区数为 n
- 集群节点数为 2n 或者 2n + 1,网络分为多个分区,导致每个节点分区数小于 n
- 多数节点网络同时异常,如机房网络异常等
- 多数节点的 mysql 服务进程同时异常退出,如机房断电等
- 其它异常
当多数节点故障后,整个集群将不可用。此时,需要重新初始化组复制集群。此时的恢复方案一般为:
- 恢复故障,比如恢复网络,或者重启节点
- 登录所有节点,执行
SHOW MASTER STATUS查看 gtid 信息,选择包含最新 gtid 信息的节点作为初始化节点,假设为 node-A - 如果node-A没有重启,首先在 node-A 上执行
STOP GROUP_REPLICATION命令,退出上一次的集群 在 node-A 上执行如下命令,启动组复制
mysql> SET GLOBAL group_replication_bootstrap_group=ON; Query OK, 0 rows affected (0.00 sec) mysql> start group_replication; Query OK, 0 rows affected (3.18 sec) mysql> SET GLOBAL group_replication_bootstrap_group=OFF; Query OK, 0 rows affected (0.00 sec)- 等待 node-A 节点处于 ONLINE 状态
对于其它节点,分别执行如下步骤,重新加入集群
- 如果该节点没有重启,执行
STOP GROUP_REPLICATION命令,退出上一次的集群 - 执行
START GROUP_REPLICATION命令加入新的组复制集群 - 等待集群处于 ONLINE 状态
- 如果该节点没有重启,执行
因为组复制本身设计实现存在的一些问题,这里需要特别注意如下一些问题:
- 可能出现
STOP GROUP_REPLICATION无法退出上一次组复制集群的问题,此时可能需要重启节点。 - 可以设置参数
group_replication_unreachable_majority_timeout,比如 30s,或者 60s 之类,如果节点没有重启,在 node-A 重新初始化集群后,且该节点已经处于 ERROR 状态时,可以自动加入到新的组复制集群中 - 由于执行
START GROUP_REPLICATION命令时,会先应用 relaylog 日志,可能导致其它节点比 node-A 多执行了事务,此时该节点无法加入集群中。这是组复制的bug,如果出现上述问题,只能先将该节点数据恢复后再加入集群。
大事务问题
组复制对大事务处理不好,如果出现大事务,可能导致集群性能吞吐下降等各种问题。解决方案是,尽量避免大事务语句。
执行语句限制问题
LOCK TABLE 语句
当集群的数据一致性级别,即参数 group_replication_consistency 大于 BEFORE 级别时,不支持执行 LOCK TABLE 语句,否则可能造成集群死锁,无法执行任何事务。
XA事务不支持
目前,组复制不能很好的支持 XA 事务,在节点出现异常时,执行 XA 事务可能导致各种问题。
无法执行只读语句
如果节点处于 ERROR 状态时,可能无法执行任何语句,包括只读的查询语句,查询 INFOMATION_SCHEMA, mysql等系统表也无法执行。此时,需要执行 STOP GROUP_REPLICATION 后,才能正常执行只读语句。
DDL语句问题
组复制支持多主写模式,但是多写不能很好的支持 DDL 语句。如果多个节点同时对同一张表进行 DDL 操作,可能导致集群异常。如果其中一个节点执行 DDL 语句,其它节点执行该表的 DML 写事务,也可能导致问题。
读写一致性问题
当前,组复制支持多种不同的一致性级别,包括:
- EVENTUAL:默认级别,不保证任何的数据一致性
- BEFORE_ON_PRIMARY_FAILOVER: 一般用于单写集群中,即
group_replication_single_primary_mode=on时,从 secondly 节点读取数据时,不保证读取到最新数据。但是如果发生主节点切换,新主会先将所有的数据应用完成之后才能提供服务。此时可能切换时间过长,导致切换时间内集群不可用。 - BEFORE:保证 secondly 节点能够读取到最新数据。同 BEFORE_ON_PRIMARY_FAILOVER 一样,存在切换时间过长的问题。
- AFTER:保证主节点写事务能够同步复制到所有的 secondly 节点,保证读写一致性。但性能消耗较大。
- BEFORE_AND_AFTER:最严格级别,保证读写一致性。
实际部署时,需要根据业务情况选择一致性级别,否则可能出现的问题包括:
- 业务不需要读一致性,但级别设置太高,导致集群性能太低
- 级别设置太低,无法满足业务读写一致性的要求
- secondly 节点配置太低,延迟太大时,导致故障切换时间太长而无法使用的问题




