MySQL 8.0 组复制(MGR)集群部署指南
在 3 台 Ubuntu 22.04 服务器上使用 MySQL 8 原生组复制搭建三节点单主高可用强一致集群,覆盖从 0 到 1 安装、Paxos 组引导/成员加入及主写从读、故障自动切换重入组实测。目标:掌握 MySQL MGR 单主集群完整搭建与容灾验证方法。
MySQL 8.0 组复制(MGR)集群部署指南
目标:在 3 台真实 Ubuntu 22.04 服务器上,使用 MySQL 8 原生组复制(MySQL Group Replication, MGR)搭建「3 节点单主」高可用、强一致集群,基于 Paxos 多数派共识实现自动故障检测与主节点选举,覆盖从 0 到 1 的完整安装、参数配置、组引导(bootstrap)、成员加入、读写验证与故障自动切换实测。已在 3 台真实服务器环境实测通过。
一、概述
MGR(MySQL Group Replication) 是 MySQL 5.7 之后引入的高可用、强一致方案,基于集团的 Paxos 共识协议实现:
- 多数派共识:写事务需得到组内多数成员确认才提交,保证副本强一致。
- 单主 / 多主:单主模式下只有一个 PRIMARY 接受写,其余为 SECONDARY 只读;多主模式所有成员都可写(本指南以单主演示)。
- 3 节点起步:约=Paxos 的多数派要求最少 3 节点,可容忍 1 台故障。
- 自动故障转移:某成员不可达时,组自动检测并重新选举 PRIMARY,其余成员继续服务。
- 对网络延迟敏感:因需要多数派确认,对节点间 RTT 有一定要求,建议同机房低延迟网络。
与《MySQL 8.0 主从复制(一主两从)部署指南》相比:主从是「异步/半同步、人工/脚本切换、可能丢数据」,MGR 是「多数派强一致、自动选主、不丢已提交数据」,更适合核心交易系统。
⚠️ 本指南原先的实验节点运行的是「异步主从 + 半同步」,其残留复制通道、
super_read_only、已应用的 GTID 集与 semi-sync 插件和 MGR 直接冲突,无法直接改建。为保证文档从 0 到 1 且可复现,新建了 3 台干净的节点重新搭建(原异步节点已停置保留)。
二、架构设计(3 节点单主)
| 角色 | 主机名 | IPv4 | server-id | group 端口 | 初始角色 |
|---|---|---|---|---|---|
| 成员 1 | mysql-mgr1 | 10.0.0.2 | 11 | 33061 | PRIMARY(首个引导) |
| 成员 2 | mysql-mgr2 | 10.0.0.3 | 12 | 33061 | SECONDARY |
| 成员 3 | mysql-mgr3 | 10.0.0.4 | 13 | 33061 | SECONDARY |
- 客户端连接 3306;组内通信(XCom/rpl 消息)走 33061。
- 组名用固定 UUID 类字符串,三台必须一致:
11111111-2222-3333-4444-555555555555。 - MGR 要求 3306 与 33061 均能内网互通,并配置
group_replication_ip_allowlist=10.0.0.0/24。 <seed 集合>即group_replication_group_seeds,三台分别写上全部成员地址。
三、环境信息表
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04 LTS(3 台,x86_64) |
| 数据库 | MySQL Server 8.0(8.0.46-0ubuntu0.22.04.4) |
| 安装方式 | 官方 apt 仓库 mysql-server |
| 复制技术 | MGR 单主(Paxos 多数派强一致 + GTID + binlog ROW) |
| 数据目录 | /var/lib/mysql;binlog /var/log/mysql/ |
| 配置追加文件 | /etc/mysql/mysql.conf.d/zz-mgr.cnf |
| 恢复账号 | rpl_mgr(组复制分布式恢复用) |
| 测试库 | shopdb(表 orders) |
💡 与普通主从相同的
mysql-server、GTID、binlog ROW 之外,MGR 额外需要transaction_write_set_extraction=XXHASH64、指定组名/端口/seeds,以及加载group_replication插件。
四、主机名与网络规划
三台主机名 mysql-mgr1/2/3。为让 MGR 用主机名互相发现(MEMBER_HOST 需能被解析),在每台 /etc/hosts 写入三条映射:
10.0.0.2 mysql-mgr1
10.0.0.3 mysql-mgr2
10.0.0.4 mysql-mgr3
验证(成员 1):
getent hosts mysql-mgr2 # -> 10.0.0.3 mysql-mgr2
ping -c 2 mysql-mgr2 # 0% loss
五、前置条件
- 3 台 Ubuntu 22.04,root/sudo 权限。
- 3306、33061 内网互通;主机名解析(第四节)。
- 三台时间同步(建议 chrony),MGR 强依赖一致性时序。
- 全新干净数据目录(无历史 GTID / 无旧复制通道),否则成员会因「已执行事务多于组」而拒绝加入(见第九节排障)。
六、一、成员 mysql-mgr1(安装 + 引导)
6.1 安装 MySQL Server(0→1)
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server
systemctl enable mysql
systemctl start mysql
mysql --version
# mysql Ver 8.0.46-0ubuntu0.22.04.4 for Linux on x86_64 ((Ubuntu))
6.2 追加 MGR 参数
/etc/mysql/mysql.conf.d/zz-mgr.cnf:
[mysqld]
server-id = 11
bind-address = 0.0.0.0
gtid_mode = ON
enforce_gtid_consistency = ON
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW
binlog_checksum = NONE
log_slave_updates = ON
relay_log = /var/log/mysql/mysql-relay-bin
transaction_write_set_extraction = XXHASH64
report_host = mysql-mgr1
loose-group_replication_group_name = "11111111-2222-3333-4444-555555555555"
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "mysql-mgr1:33061"
loose-group_replication_group_seeds = "mysql-mgr1:33061,mysql-mgr2:33061,mysql-mgr3:33061"
loose-group_replication_bootstrap_group = OFF
loose-group_replication_single_primary_mode = ON
loose-group_replication_enforce_update_everywhere_checks = OFF
loose-group_replication_ip_allowlist = "10.0.0.0/24"
loose-group_replication_recovery_get_public_key = ON
要点:
transaction_write_set_extraction = XXHASH64:MGR 冲突检测所需,三台一致。binlog_checksum = NONE:MGR 要求的 binlog 校验设置。group_replication_single_primary_mode = ON:单主;= OFF即为多主。group_replication_start_on_boot = OFF:重启后不自动加入组,需手动START GROUP_REPLICATION(便于维护/排障,后面会演示)。loose-前缀使插件未加载时也不报"未知变量"。
⚠️
loose-只能"忍"未知变量,不会加载插件。MGR 变量要生效,必须先INSTALL PLUGIN group_replication(见 6.4)。
6.3 重启使配置生效
systemctl restart mysql
sleep 3
6.4 加载 group_replication 插件并重启
mysql -uroot -e "INSTALL PLUGIN group_replication SONAME 'group_replication.so';"
systemctl restart mysql
sleep 3
pgrep -x mysqld && echo "mysqld running"
确认插件 ACTIVE 与关键参数:
mysql -uroot -N -e "SELECT PLUGIN_NAME, PLUGIN_STATUS FROM information_schema.PLUGINS WHERE PLUGIN_NAME='group_replication';"
# group_replication ACTIVE
mysql -uroot -N -e "SELECT @@group_replication_single_primary_mode, @@group_replication_group_name;"
# 1 11111111-2222-3333-4444-555555555555
6.5 创建分布式恢复账号(每个成员都要建)
MGR 成员加入时通过 group_replication_recovery 通道连接捐赠者拉取数据,需要专用账号:
mysql -uroot <<'SQL'
CREATE USER IF NOT EXISTS 'rpl_mgr'@'%' IDENTIFIED WITH caching_sha2_password BY 'RplMgr@2026';
GRANT REPLICATION SLAVE, BACKUP_ADMIN, SYSTEM_VARIABLES_ADMIN, GROUP_REPLICATION_ADMIN ON *.* TO 'rpl_mgr'@'%';
FLUSH PRIVILEGES;
SQL
💡 恢复通道账号在每个成员生效前都要存在;
group_replication_recovery_get_public_key=ON让非 SSL 的 caching_sha2 握手能取到公钥(否则报公钥/握手错误)。
6.6 引导(bootstrap)整个组(只在第一个成员执行一次)
mysql -uroot <<'SQL'
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
SQL
首个成员先起,成为 PRIMARY:
mysql -uroot -e "SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members;"
实测回显:
MEMBER_HOST MEMBER_STATE MEMBER_ROLE
mysql-mgr1 ONLINE PRIMARY
七、二、成员 mysql-mgr2(安装 + 加入)
7.1 安装(0→1,与成员 1 完全相同的步骤)
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server
systemctl enable mysql && systemctl start mysql
mysql --version
7.2 追加 MGR 参数(仅 server-id 与 local_address 不同,=12)
/etc/mysql/mysql.conf.d/zz-mgr.cnf:
[mysqld]
server-id = 12
bind-address = 0.0.0.0
gtid_mode = ON
enforce_gtid_consistency = ON
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW
binlog_checksum = NONE
log_slave_updates = ON
relay_log = /var/log/mysql/mysql-relay-bin
transaction_write_set_extraction = XXHASH64
report_host = mysql-mgr2
loose-group_replication_group_name = "11111111-2222-3333-4444-555555555555"
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "mysql-mgr2:33061"
loose-group_replication_group_seeds = "mysql-mgr1:33061,mysql-mgr2:33061,mysql-mgr3:33061"
loose-group_replication_bootstrap_group = OFF
loose-group_replication_single_primary_mode = ON
loose-group_replication_enforce_update_everywhere_checks = OFF
loose-group_replication_ip_allowlist = "10.0.0.0/24"
loose-group_replication_recovery_get_public_key = ON
7.3 重启并加载插件
systemctl restart mysql
mysql -uroot -e "INSTALL PLUGIN group_replication SONAME 'group_replication.so';"
systemctl restart mysql
sleep 3
7.4 建恢复账号(与 6.5 相同)
mysql -uroot <<'SQL'
CREATE USER IF NOT EXISTS 'rpl_mgr'@'%' IDENTIFIED WITH caching_sha2_password BY 'RplMgr@2026';
GRANT REPLICATION SLAVE, BACKUP_ADMIN, SYSTEM_VARIABLES_ADMIN, GROUP_REPLICATION_ADMIN ON *.* TO 'rpl_mgr'@'%';
FLUSH PRIVILEGES;
SQL
7.5 加入组(不 bootstrap,直接 START)
mysql -uroot -e "START GROUP_REPLICATION;"
⚠️ 若此前在本机执行过任何 DML/DDL(哪怕只是
CREATE USER),会产生不属于组的本地 GTID,加入时报“本成员已执行事务多于组”。此时需在本机RESET MASTER清空执行集再加入(见 7.6 / 第九节)。
7.6 若不干净:清空本地 GTID 后重新加入
mysql -uroot <<'SQL'
RESET MASTER; # 清空本机 gtid_executed 执行集(仅空/干净数据安全)
START GROUP_REPLICATION;
SQL
⚠️
RESET MASTER只对「本机无业务数据」的新成员安全;已有要保留的数据绝对不要用。
八、三、成员 mysql-mgr3
安装与加入与成员 2 完全相同,仅配置不同:
8.1 安装 + 插件
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server
systemctl enable mysql && systemctl start mysql
8.2 MGR 参数(server-id=13、local_address=mysql-mgr3)
[mysqld]
server-id = 13
bind-address = 0.0.0.0
gtid_mode = ON
enforce_gtid_consistency = ON
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW
binlog_checksum = NONE
log_slave_updates = ON
relay_log = /var/log/mysql/mysql-relay-bin
transaction_write_set_extraction = XXHASH64
report_host = mysql-mgr3
loose-group_replication_group_name = "11111111-2222-3333-4444-555555555555"
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "mysql-mgr3:33061"
loose-group_replication_group_seeds = "mysql-mgr1:33061,mysql-mgr2:33061,mysql-mgr3:33061"
loose-group_replication_bootstrap_group = OFF
loose-group_replication_single_primary_mode = ON
loose-group_replication_enforce_update_everywhere_checks = OFF
loose-group_replication_ip_allowlist = "10.0.0.0/24"
loose-group_replication_recovery_get_public_key = ON
8.3 重启 + 插件 + 恢复账号 + 加入
systemctl restart mysql
mysql -uroot -e "INSTALL PLUGIN group_replication SONAME 'group_replication.so';"
systemctl restart mysql
mysql -uroot <<'SQL'
CREATE USER IF NOT EXISTS 'rpl_mgr'@'%' IDENTIFIED WITH caching_sha2_password BY 'RplMgr@2026';
GRANT REPLICATION SLAVE, BACKUP_ADMIN, SYSTEM_VARIABLES_ADMIN, GROUP_REPLICATION_ADMIN ON *.* TO 'rpl_mgr'@'%';
FLUSH PRIVILEGES;
SQL
mysql -uroot -e "RESET MASTER;"
mysql -uroot -e "START GROUP_REPLICATION;"
九、组引导后验证与恢复通道要点
三个成员都加入后,在任一成员查看组拓扑:
mysql -uroot -e "SELECT MEMBER_HOST, MEMBER_PORT, MEMBER_STATE, MEMBER_ROLE, MEMBER_VERSION FROM performance_schema.replication_group_members;"
实测回显:
MEMBER_HOST MEMBER_PORT MEMBER_STATE MEMBER_ROLE MEMBER_VERSION
mysql-mgr1 3306 ONLINE PRIMARY 8.0.46
mysql-mgr2 3306 ONLINE SECONDARY 8.0.46
mysql-mgr3 3306 ONLINE SECONDARY 8.0.46
身份与读写口径(单主):
# 谁是 PRIMARY
mysql -uroot -N -e "SELECT MEMBER_HOST FROM performance_schema.replication_group_members WHERE MEMBER_ROLE='PRIMARY' AND MEMBER_STATE='ONLINE';"
# 各成员只读状态(主 0 / 从 1)
mysql -uroot -N -e "SELECT @@read_only;"
💡 MGR 单主下,SECONDARY 的
read_only由组自动置为 1,PRIMARY 为 0,业务无需手工维护。
9.1 恢复通道(group_replication_recovery)
成员加入时通过该通道从捐赠者拉取增量数据。首次加入若报 "Invalid (empty) username",表示没给恢复通道指定账号,手动补齐:
mysql -uroot <<'SQL'
STOP GROUP_REPLICATION;
CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_mgr', SOURCE_PASSWORD='RplMgr@2026' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;
SQL
⚠️ 引导(bootstrap)的首个成员不需要恢复通道;后续每个加入的成员都需要配置此通道(且远端成员上也必须有
rpl_mgr账号才能被连上)。
十、功能测试(强一致 / 读写 / 故障容灾)
10.1 主库写入强一致复制
在 PRIMARY(mysql-mgr1) 建库建表,建应用账号,写入 1 行:
mysql -uroot <<'SQL'
CREATE USER IF NOT EXISTS 'appuser'@'%' IDENTIFIED BY 'App@2026';
CREATE DATABASE IF NOT EXISTS shopdb;
USE shopdb;
CREATE TABLE IF NOT EXISTS orders (id INT AUTO_INCREMENT PRIMARY KEY, customer VARCHAR(50), amount DECIMAL(10,2)) ENGINE=InnoDB;
INSERT INTO orders (customer,amount) VALUES ('mgr_paxos', 66.60);
GRANT ALL PRIVILEGES ON shopdb.* TO 'appuser'@'%';
SELECT COUNT(*) FROM shopdb.orders;
SQL
三个成员同时可读到该事务(强一致性验证):
# PRIMARY
mysql -uroot -N -e "SELECT COUNT(*) FROM shopdb.orders;" # 1
mysql -uroot -N -e "SELECT COUNT(*) FROM shopdb.\`orders\`;" # mysql-mgr2 上:# 1
mysql -uroot -N -e "SELECT COUNT(*) FROM shopdb.\`orders\`;" # mysql-mgr3 上:# 1
10.2 SECONDARY 只读验证(拒绝直写)
在 SECONDARY(mysql-mgr2) 用应用账号直接插入,应被拒绝:
mysql -uappuser -pApp@2026 -e "INSERT INTO shopdb.orders (customer,amount) VALUES ('forbidden',1);"
实测回显:
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
10.3 GTID 强一致(三成员执行集完全一致)
mysql -uroot -N -e "SELECT @@GLOBAL.gtid_executed;"
实测回显(mysql-mgr1 / mgr2 / mgr3 三台完全一致):
11111111-2222-3333-4444-555555555555:1-14:1000007,
f93682a6-bc1d-11f1-a678-d69c1bed5844:1-3
三个成员 gtid_executed 集合一致,即多数派确认、无丢失。
10.4 故障自动切换(Paxos 选主)
停掉当前的 PRIMARY 主机 mysql-mgr1(等价于主库宕机),等待故障检测与重选:
# 停 PRIMARY 主机 mysql-mgr1
# 等待 ~25s 后,在 mysql-mgr2 查看
mysql -uroot -e "SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members;"
mysql -uroot -N -e "SELECT MEMBER_HOST FROM performance_schema.replication_group_members WHERE MEMBER_ROLE='PRIMARY';"
实测回显:
MEMBER_HOST MEMBER_STATE MEMBER_ROLE
mysql-mgr2 ONLINE PRIMARY <- 自动被选举为新主
mysql-mgr3 ONLINE SECONDARY
(新 PRIMARY)
mysql-mgr2
故障后 mysql-mgr2 自动成为新 PRIMARY,无需人工干预;新主上继续写、继续同步到 mysql-mgr3:
mysql -uroot -e "INSERT INTO shopdb.orders (customer,amount) VALUES ('new_primary_ok',7.7);"
# mysql-mgr3 上
mysql -uroot -N -e "SELECT COUNT(*) FROM shopdb.\`orders\`;"
# 2
10.5 旧主恢复并重新加入(不会抢占主)
由于 group_replication_start_on_boot = OFF,mysql-mgr1 恢复后不会自动加入;先补齐它的恢复通道账号再手动加入:
mysql -uroot <<'SQL'
CREATE USER IF NOT EXISTS 'rpl_mgr'@'%' IDENTIFIED WITH caching_sha2_password BY 'RplMgr@2026';
GRANT REPLICATION SLAVE, BACKUP_ADMIN, SYSTEM_VARIABLES_ADMIN, GROUP_REPLICATION_ADMIN ON *.* TO 'rpl_mgr'@'%';
FLUSH PRIVILEGES;
SQL
mysql -uroot <<'SQL'
STOP GROUP_REPLICATION;
CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_mgr', SOURCE_PASSWORD='RplMgr@2026' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;
SQL
旧主自动追平数据并以 SECONDARY 身份在线:
mysql -uroot -e "SELECT MEMBER_HOST, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members;"
实测回显(最终拓扑,mysql-mgr2 仍为主):
MEMBER_HOST MEMBER_STATE MEMBER_ROLE
mysql-mgr1 ONLINE SECONDARY <- 重加入,未抢主
mysql-mgr2 ONLINE PRIMARY
mysql-mgr3 ONLINE SECONDARY
三个成员 orders 行数均为 2,数据完全一致。
十一、常见问题
11.1 Unknown system variable 'group_replication_bootstrap_group'
group_replication 插件未加载(loose- 只是容忍未知变量,不加载插件)。执行:
mysql -uroot -e "INSTALL PLUGIN group_replication SONAME 'group_replication.so';"
systemctl restart mysql
11.2 加入时报 This member has more executed transactions than the group
本机存在不属于组的本地 GTID(如曾创建过用户/表或做过复制)。若是干净新节点:
mysql -uroot -e "RESET MASTER;" # 清空本机执行集(仅无业务数据时安全)
mysql -uroot -e "START GROUP_REPLICATION;"
11.3 恢复通道报 Invalid (empty) username
恢复通道没指定账号;补齐恢复通道凭据并重启组复制:
STOP GROUP_REPLICATION;
CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_mgr', SOURCE_PASSWORD='RplMgr@2026' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;
11.4 恢复连接报 caching_sha2 公钥/SSL 错误
恢复通道连接走非 SSL,需开启公钥获取:
loose-group_replication_recovery_get_public_key = ON
11.5 节点长期卡 RECOVERING
- 检查
SHOW REPLICA STATUS FOR CHANNEL 'group_replication_recovery'\G的Last_IO_Error; - 确认捐赠者(PRIMARY)上有
rpl_mgr账号且可连通; - 确认 33061 互通、
group_replication_ip_allowlist覆盖成员网段。
11.6 MGR 对网络要求
多数派确认对 RTT 敏感:成员间建议 <5ms、同机房;跨地域或高丢包会导致频繁重选/部分成员不可达,属正常现象,需优先网络治理。
十二、常用状态查询(运维速查)
# 组拓扑与角色
SELECT * FROM performance_schema.replication_group_members;
# 各成员统计(事务数、冲突数)
SELECT * FROM performance_schema.replication_group_member_stats\G
# 恢复/应用通道线程状态
SHOW REPLICA STATUS FOR CHANNEL 'group_replication_applier'\G
# 一致性质检:三台 gtid_executed 应完全一致
SELECT @@GLOBAL.gtid_executed;
十三、清理与卸载
# 退出组(组成员上执行;PRIMARY 先降级则退出后另有主继续)
mysql -uroot -e "STOP GROUP_REPLICATION;"
# 卸载本机 MySQL(保留 /var/lib/mysql)
apt-get remove -y mysql-server
# 彻底清理(含数据,慎用)
# apt-get purge -y mysql-server mysql-server-8.0 mysql-common && rm -rf /var/lib/mysql
十四、参考链接
- MySQL 8 Group Replication 概览:https://dev.mysql.com/doc/refman/8.0/en/group-replication.html
- Group Replication 部署示例:https://dev.mysql.com/doc/refman/8.0/en/group-replication-deploying.html
- Group Replication 变量:https://dev.mysql.com/doc/refman/8.0/en/group-replication-system-variables.html
- Group Replication 状态表:https://dev.mysql.com/doc/refman/8.0/en/group-replication-monitoring.html