MySQL 8.0 组复制(MGR)集群部署指南

在 3 台 Ubuntu 22.04 服务器上使用 MySQL 8 原生组复制搭建三节点单主高可用强一致集群,覆盖从 0 到 1 安装、Paxos 组引导/成员加入及主写从读、故障自动切换重入组实测。目标:掌握 MySQL MGR 单主集群完整搭建与容灾验证方法。

MySQLMySQL数据库组复制2026/09/30

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 节点单主)

角色主机名IPv4server-idgroup 端口初始角色
成员 1mysql-mgr110.0.0.21133061PRIMARY(首个引导)
成员 2mysql-mgr210.0.0.31233061SECONDARY
成员 3mysql-mgr310.0.0.41333061SECONDARY
  • 客户端连接 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

十四、参考链接