不停服务快速创建一个MySQL从节点加入已经存在的MGR集群中
记录一下因故障导致原来MGR集群中的一个节点无法恢复,而需要清空重新创建的步骤
目录
- 一、环境说明
- 二、创建步骤
- 2.1 先查看当前环境
- 2.2 创建新数据库(新节点)
- 2.3 提供必要账户(主节点)
- 2.4 执行数据克隆(新节点)
- 2.5 执行加入集群(新节点)
- 2.6 验证加入状态(新节点)
- 2.7 参数一致修改(所有节点)
- 三、故障处理
一、环境说明
- 版本 MySQL 8.0.27
- 一主两从3台服务器做的MGR集群
当前MGR集群中是一主一从,现在要重新创建新节点加入这个集群- Linux 系统环境
- Docker 容器化环境
| 当前主机 | 节点类别 |
|---|---|
| 192.168.30.222 | PRIMARY 主节点 |
| 192.168.30.247 | SECONDARY 从节点 |
192.168.30.229 | 准备要创建的新节点 |
二、创建步骤
2.1 先查看当前环境
在当前MGR集群中查询如下:
mysql> SELECT * FROM `performance_schema`.replication_group_members;
另外查询当前集群状态值:
mysql> SHOW VARIABLES LIKE 'group_replication%';
查询当前情况谁是主节点,当然如果你们已经使用MySQL Proxy 或者 Router连接了集群就直接使用这个代理客户端连接当前集群查询。
注意: 所有服务器的 hostname 确保不一样 ,
如果修改主机名称使用类似如下命令:
sudo hostnamectl set-hostname NEWHOSTNAMEHERE
另外记得修改当前所有节点服务器上 /etc/hosts 文件中的内容,将本次所有的主机名称配置对应IP地址,
特别注意第1、2两行
127.0.0.1的对应关系127.0.0.1 localhost
127.0.1.1 mgr-node1192.168.30.222 mgr-master mgr-master
192.168.30.247 mgr-node1 mgr-node1
192.168.30.229 mgr-node2 mgr-node2
2.2 创建新数据库(新节点)
在本次主机 192.168.30.229 使用docker容器创建一个新的空的数据库。
注意:版本必须和集群中的MySQL版本一致,避免其他异常情况发生
当前容器映射主机路径是 /data/apps/mgr,目录下创建如下的子目录。
root@middol-desktop:/data/apps/mgr# ll
total 20
drwxr-xr-x 5 root root 4096 11月 6 17:30 ./
drwxr-xr-x 6 root root 4096 11月 6 18:48 ../
drwxr-xr-x 2 root root 4096 11月 7 10:20 conf/
drwxr-xr-x 23 systemd-coredump root 4096 11月 6 22:05 data/
drwxr-xr-x 2 root root 4096 11月 6 17:30 files/
conf目录下创建MySQL配置文件 my.cnf,我这边是测试环境8G内存,实际情况根据各自环境修改参数大小。
[client]
port = 3319
socket =/var/lib/mysql/mysqld.sock[mysql]
no-auto-rehash[mysqld]
port = 3319
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysqld.sock
log-error = /var/lib/mysql/error.log
pid-file = /var/lib/mysql/mysqld.pidadmin_port = 33064
mysqlx-port = 33063#
# Disable other storage engines
#
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"skip_name_resolve = 1
default_time_zone = "+8:00"
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
init_connect='SET NAMES utf8mb4'
lower_case_table_names = 1
transaction_isolation = READ-COMMITTED
explicit_defaults_for_timestamp = true
open_files_limit = 65535
max_connections = 300
max_connect_errors = 600
back_log = 110
table_open_cache = 600
table_definition_cache = 700
table_open_cache_instances = 64
thread_stack = 512K
external-locking = FALSE
max_allowed_packet = 128M
sort_buffer_size = 4M
join_buffer_size = 4M
thread_cache_size = 20interactive_timeout = 1800
wait_timeout = 1800lock_wait_timeout = 3600tmp_table_size = 64M
max_heap_table_size = 64Mserver-id = 5#--###########################-- binlog配置 --##########################################
log-bin=mysql-binbinlog_format = ROW
binlog_row_image = FULL
binlog_expire_logs_seconds = 1209600
master_info_repository = TABLE
relay_log_info_repository = TABLE
log_replica_updates = ON
relay_log_recovery = 1
replica_skip_errors = ddl_exist_errors
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
transaction_write_set_extraction = XXHASH64binlog_cache_size = 4M
max_binlog_cache_size = 2G
max_binlog_size = 1G
gtid_mode = on
enforce_gtid_consistency=ON
# MySQL 8.0.21可以不设置
#binlog_checksum=NONEkey_buffer_size = 15M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M#--###########################-- innodb配置 --##########################################
innodb_thread_concurrency = 0
innodb_buffer_pool_size = 4G
innodb_buffer_pool_instances = 4
innodb_buffer_pool_load_at_startup = 1
innodb_buffer_pool_dump_at_shutdown = 1
innodb_data_file_path = ibdata1:1G:autoextend
innodb_log_buffer_size = 32M
innodb_log_files_in_group = 3
innodb_log_file_size = 2G
innodb_undo_log_truncate = 1
innodb_max_undo_log_size = 2G
innodb_io_capacity = 4000
innodb_io_capacity_max = 8000
innodb_flush_sync = 0
innodb_flush_neighbors = 0
innodb_write_io_threads = 8
innodb_read_io_threads = 8
innodb_purge_threads = 4
innodb_page_cleaners = 4
innodb_open_files = 65535
innodb_max_dirty_pages_pct = 50
innodb_flush_method = O_DIRECT
innodb_lru_scan_depth = 4000
innodb_checksum_algorithm = crc32
innodb_lock_wait_timeout = 20
innodb_rollback_on_timeout = 1
innodb_print_all_deadlocks = 1
innodb_sort_buffer_size = 67108864
innodb_autoinc_lock_mode = 1
innodb_file_per_table = 1
innodb_online_alter_log_max_size = 4G[mysqldump]
quick
max_allowed_packet = 128M
创建MySQL容器:
注意修改root账号的密码 MYSQL_ROOT_PASSWORD
docker run -u root \--cap-add=SYS_NICE \--network=host \--restart=always \--name mgr8 \-v /data/apps/mgr/conf/my.cnf:/etc/mysql/my.cnf \-v /data/apps/mgr/files:/var/lib/mysql-files \-v /data/apps/mgr/data:/var/lib/mysql \-e MYSQL_ROOT_PASSWORD=YourPassword123456_ \-d mysql:8.0.27
可以查看 /data/apps/mgr/data 下看下是否创建成功。
tail -f data/error.log
如果成功后,则登录这个数据库中做如下处理:
- 登录这个新数据库中
mysql -uroot -p -P3319 -h192.168.30.229
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 83283
Server version: 8.0.27 MySQL Community Server - GPLCopyright (c) 2000, 2021, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>
- 安装克隆数据的插件
mysql> INSTALL PLUGIN clone SONAME 'mysql_clone.so';
mysql> SHOW PLUGINS;
- 设置可以克隆节点列表
这一步必须设置,否则无法克隆主节点的数据
mysql> SET GLOBAL clone_valid_donor_list = '192.168.30.222:3319,192.168.30.247:3319';
2.3 提供必要账户(主节点)
在主节点上必须提供用于复制与克隆账号,如果已经存在则无需下面的操作,如果没有则执行下面的操作。
在 主节点(node1) 执行以下 SQL,创建复制与克隆账号:
CREATE USER 'clone_user'@'%' IDENTIFIED WITH mysql_native_password BY 'YourPassword123456_';
GRANT BACKUP_ADMIN, CLONE_ADMIN ON *.* TO 'clone_user'@'%';CREATE USER 'rep_user'@'%' IDENTIFIED WITH mysql_native_password BY 'YourPassword123456_';
GRANT REPLICATION SLAVE ON *.* TO 'rep_user'@'%';FLUSH PRIVILEGES;
- clone_user 用于新数据库克隆当前主节点的数据库数据。
- rep_user 用于新数据库克隆之后加入MGR集群后复制数据使用。
- 创建账户时使用
mysql_native_password密码认证模式,否则复制会无法执行,这应该是一个BUG。
2.4 执行数据克隆(新节点)
登录新节点的数据库上执行如下命令:
mysql> CLONE INSTANCE FROM 'clone_user'@'192.168.30.222':3319 IDENTIFIED BY 'YourPassword123456_';
如果不出意外,执行后会::
- 自动停止 MySQL的对外服务;
- 拷贝主节点全量数据;
- 自动重启。
重新登录后验证是否已经克隆了当前主节点的数据。
注意:再次登录时,需要使用当前MGR集群中账号的密码, 而不是上面你新创建的数据库root用户密码,因为数据已经被覆盖
2.5 执行加入集群(新节点)
修改新节点数据库的 my.cnf配置文件,增加MGR相关配置参数:
report_host = "192.168.30.229"
group_replication_group_name = "7cf70110-59f9-11ee-a293-246e967fa518"
group_replication_start_on_boot = OFF
group_replication_local_address = "192.168.30.229:33071"
group_replication_group_seeds = "192.168.30.222:33061,192.168.30.229:33071,192.168.30.247:33071"
group_replication_ip_allowlist = "127.0.0.1,192.168.30.0/24"
group_replication_bootstrap_group = OFF
重启新节点 MySQL:
docker restart mgr8
重新登录新节点,准备加入集群:
先确认group集群查询是否已经存在,一般情况下已经存在了,如果不存在则新增一下即可:
mysql> SHOW PLUGINS;# 如果不存在 group_replication 插件,则执行安装操作
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
加入集群:
mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='YourPassword123456_';
2.6 验证加入状态(新节点)
mysql> SELECT * FROM performance_schema.replication_group_members;
预期结果:
| member_host | member_state | member_role |
|---|---|---|
| 192.168.30.222 | ONLINE | PRIMARY |
| 192.168.30.247 | ONLINE | SECONDARY |
| 192.168.30.229 | ONLINE | SECONDARY |
注意:如果你之前的节点没有配置report_host参数,则此时的member_host值会是各自服务器的hostname
集群复制健康监控:
SELECT * FROM performance_schema.replication_group_member_stats;
日志排查
error.log 若报 Group_replication_applier thread error ⇒ 一般是数据不一致。
RECOVERING 状态长时间卡住 ⇒ 端口或凭证问题。
2.7 参数一致修改(所有节点)
确保其他节点上的一些参数必须一致:
- group_replication_group_seeds 全部一致
- group_replication_ip_allowlist 全部一致
- group_replication_start_on_boot 建议全部设置为ON,开机自动加入集群
在每个节点上修改变量的值(运行时修改):
举例设置 group_replication_group_seeds
SET GLOBAL group_replication_group_seeds = "192.168.30.222:33061,192.168.30.229:33071,192.168.30.247:33071";
再同步修改到配置文件(my.cnf)
[mysqld]
group_replication_start_on_boot = ON
group_replication_group_seeds = "192.168.30.222:33061,192.168.30.229:33071,192.168.30.247:33071"
group_replication_ip_allowlist = "127.0.0.1,192.168.30.0/24"
三、故障处理
以上步骤出现错误,大致的错误可能的原因如下:
- 防火墙阻止了复制端口
服务器hostname出现相同,且report_host没有设置- 组复制使用的内部通信端口(默认 33061)被已经存在的MySQL服务占用
- group_replication_local_address 参数配置错误
- SELinux 未关闭
请确保主节点暂时无大事务操作- 版本差异/配置冲突
主要关注如下两张信息表数据:
SELECT * FROM performance_schema.replication_applier_status;
SELECT * FROM performance_schema.replication_connection_status;
replication_connection_status | replication_applier_status | |
|---|---|---|
| 作用层次 | 复制的「网络连接状态」 | 复制的「事务应用状态」 |
| 角色定位 | 负责从上游 (source/master) 获取 binlog 数据 | 负责在本地执行接收到的事务事件 |
| 对应传统复制部分 | I/O 线程 (Slave_IO_Thread) | SQL 线程 (Slave_SQL_Thread) |
| 关注内容 | 网络连接、接收 binlog、位点(GTID/Binlog 文件位置) | relay log 应用、事务延迟、是否出错 |
| 何时存在 | 节点需要从别的节点获取日志时(比如 group_replication_recovery 通道) | 每个处于复制状态的节点都会有(如 group_replication_applier) |
| 典型通道名 | group_replication_recovery | group_replication_applier |
| 状态方向 | 从「别的节点读取日志」 | 将「日志应用到本地」 |
| 代表的线程 | IO 线程 | SQL 执行线程(worker) |
想象 MGR 或异步复制是一个“流水线”:
[主节点 Binlog] --> (复制 IO 线程) --> [本地 Relay Log] --> (Applier 线程) --> [实际数据库表]↑ ↑replication_connection_status replication_applier_status
在 Group Replication (MGR) 中的体现
| 场景 | 相关通道 | 查询哪张表 |
|---|---|---|
| 新节点加入组(恢复阶段) | group_replication_recovery | replication_connection_status(是否在拉取binlog) |
| 节点已在组内正常运行 | group_replication_applier | replication_applier_status(是否在应用事务) |
| 节点掉线/延迟 | 两者可能都可见错误 | 需同时查两张表分析 |
-- 查看连接层
SELECT CHANNEL_NAME, SERVICE_STATE, SOURCE_HOST, LAST_ERROR_MESSAGE
FROM performance_schema.replication_connection_status;-- 查看应用层
SELECT CHANNEL_NAME, SERVICE_STATE, LAST_APPLIED_TRANSACTION, LAST_ERROR_MESSAGE
FROM performance_schema.replication_applier_status;
🔹 如果第一个表返回空,而第二个表 SERVICE_STATE=ON → 节点处于正常运行中
🔹 如果第一个表有 group_replication_recovery 且 SERVICE_STATE=ON → 节点正在同步恢复
🔹 如果任何一个表的 LAST_ERROR_MESSAGE 不为空 → 节点出现复制/同步问题
+-------------------------------+
| 组内其他节点(donor) |
| ├─> Binlog stream |
| └─> GCS 消息(实时事务) |
+-------------------------------+│▼┌──────────────────────────────┐│ 本节点(joining / member) ││ ││ ① 初始同步阶段(节点加入时) ││ ➤ 启动: group_replication_recovery 通道│ ➤ 状态记录在: replication_connection_status│ ││ ② 同步完成后进入组 ││ ➤ 停止: group_replication_recovery│ ➤ 长期运行: group_replication_applier 通道│ ➤ 状态记录在: replication_applier_status└──────────────────────────────┘
诊断小技巧
| 场 景 | 应查看的通道 | 应查的表 | 正常现象 |
|---|---|---|---|
| 新节点加入 MGR | group_replication_recovery | replication_connection_status | 看到一条记录,状态 ON |
| 节点同步完成 | 无 group_replication_recovery | replication_applier_status 存在 1 行,状态 ON | |
| 节点卡在 RECOVERING | group_replication_recovery 存在但长期不消失 | replication_connection_status 中有错误 | |
| 节点已 ONLINE 但事务未实时更新 | 检查 group_replication_applier | replication_applier_status LAST_ERROR_MESSAGE 是否为空 |
thanks !
