MySQL 8.0.35 MGR (Group Replication) 完整部署与验证

环境:3 节点 MGR(192.168.195.141 / 142 / 143,均 CentOS 系 Kylin V10,2.8G 内存),MySQL 8.0.35 二进制包(官方归档源)
覆盖:MGR.pdf 全部内容 – 架构原理、部署(单主/多主)、全部管理操作(在线切换/手动切主/加减节点/clone 重建)、常见故障模拟与解决、监控、知识点补充
验证状态:12 个场景全部实测通过(单主 failover、多主并发写、冲突检测、脑裂防护、clone 重建、权重选举等)
所有命令注明执行节点,老板可按文档逐步复现。


一、MGR 架构原理(PDF 核心章节精要)

1.1 什么是 MGR

MySQL Group Replication:基于 Paxos 变种(XCom/Paxos 协议)实现的多写复制插件,提供自动故障检测、自动 failover、强一致性(多数派认证)

三大特点(PDF 原文要点):

  1. 高可用:成员故障自动剔除/检测,单主模式自动选举新主(秒级)
  2. 强一致:事务经多数派(N/2+1)认证才提交,无数据丢失风险(RPO=0)
  3. 弹性:在线加减节点、在线单主<->多主模式切换

1.2 单主 vs 多主(PDF 对比)

维度单主模式 (single-primary)多主模式 (multi-primary)
写入点仅 PRIMARY 一个(SECONDARY 全部 super_read_only)所有成员均可写
冲突无(写冲突不可能发生)存在,靠认证机制检测回滚
二级制日志binlog + applier 并行同左
适用绝大多数业务(默认推荐)特殊多写需求/跨地域写
隔离级别默认 REPEATABLE READ建议读已提交 + ROW 格式
性能高(无认证开销集中)相对低(每个事务都认证)

1.3 事务认证流程(PDF 认证章节)

客户端事务(本地BEGIN..UPDATE..COMMIT)
  └─> 本地执行,产生 write set(XXHASH64 提取)
      └─> 组播给所有成员(XCom/Paxos 全序广播)
          ├─> 各成员认证器(certifier)比对 write set:
          │     若与已认证事务的 write set 无冲突 → 认证通过
          │     冲突 → 后到者回滚(客户端收到 ERROR)
          └─> 多数派(N/2+1)达成一致 → 提交
              └─> 各成员 applier 异步应用(relay log → binlog)

冲突检测本质:比对事务修改行的主键 write set。两个并发事务改同一行,先认证者胜出,后到者在所有成员上被回滚(包括发起者)。

1.4 多数派与脑裂防护

  • 3 节点组:需 2 台存活(多数派)才能对外服务
  • 网络分区时少数派无法达成多数派认证,事务无法提交(卡住直至超时),不会脑裂写数据
  • group_replication_unreachable_majority_timeout:少数派超时退出组(默认 0 不退出),生产建议设置

二、架构规划(本环境)

MGR 集群(单主起步,后续在线切多主):
  192.168.195.141  server-id=1  初始引导为 PRIMARY
  192.168.195.142  server-id=2  SECONDARY
  192.168.195.143  server-id=3  SECONDARY

组通信端口: 33061 (每节点的 group_replication_local_address)
MySQL 服务端口: 3306
组名(UUID): 982e833d-9c5e-4bcb-a36a-d05573d03bb8  (uuidgen 生成,三节点必须一致)

为什么这样规划:3 节点是 MGR 最小高可用单元(容忍 1 台故障);单主模式是生产默认;组通信端口独立于 3306 便于防火墙策略。


三、环境清理(三节点执行)

清理旧 MySQL / Orchestrator / MHA / Docker / VIP 残留:

# 执行节点: 141/142/143 分别执行
ip addr del 192.168.195.200/24 dev ens32 2>/dev/null
systemctl stop mysqld orchestrator orch-smtp 2>/dev/null
systemctl disable mysqld orchestrator orch-smtp 2>/dev/null
rm -rf /etc/systemd/system/mysqld.service /etc/systemd/system/orchestrator.service \
       /etc/systemd/system/orch-smtp.service /data/mysql /etc/my.cnf /etc/my3307.cnf \
       /etc/sysconfig/mysql /home/orchestrator /var/lib/orchestrator /var/log/orchestrator \
       /var/mailbox /opt/smtp_server.py /etc/profile.d/orchestrator-client.sh \
       /etc/masterha /var/log/masterha /usr/local/bin/orchestrator-client /usr/local/bin/masterha*
rpm -e mha4mysql-node mha4mysql-manager 2>/dev/null
rm -rf /usr/local/mysql /usr/local/mysql-8.0.35-linux-glibc2.17-x86_64
userdel -r mysql 2>/dev/null; userdel -r orchestrator 2>/dev/null
systemctl daemon-reload
# 验证: 无 mysqld/orchestrator 进程, /usr/local/mysql 不存在, id mysql 报无此用户

四、MySQL 8.0.35 安装(三节点)

4.1 下载(官方归档源,国内镜像无 8.0.35)

# 执行节点: 141(下载后 scp 分发)
cd /usr/local/src
curl -sL -o mysql-8.0.35-linux-glibc2.17-x86_64.tar.xz \
  "https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.35-linux-glibc2.17-x86_64.tar.xz"
md5sum mysql-8.0.35-linux-glibc2.17-x86_64.tar.xz
# c17075cfc58d8cd25cea4be36d77eed2  (三节点必须一致)
scp mysql-8.0.35-linux-glibc2.17-x86_64.tar.xz root@192.168.195.142:/usr/local/src/
scp mysql-8.0.35-linux-glibc2.17-x86_64.tar.xz root@192.168.195.143:/usr/local/src/

国内源尝试记录:清华 tuna / 阿里 / 腾讯 / 华为 / 中科大镜像的 MySQL-8.0 目录均只到 8.0.28(glibc2.17 完整包),无 8.0.35,故用官方归档源(可达,419MB,速度快)。

4.2 用户与解压(三节点)

# 执行节点: 141/142/143
groupadd -f mysql && useradd -g mysql -s /sbin/nologin mysql
cd /usr/local && tar xf /usr/local/src/mysql-8.0.35-linux-glibc2.17-x86_64.tar.xz
ln -sf mysql-8.0.35-linux-glibc2.17-x86_64 mysql
mkdir -p /data/mysql/3306/data && chown -R mysql:mysql /data/mysql
/usr/local/mysql/bin/mysql --version   # Ver 8.0.35

4.3 my.cnf(MGR 核心,三节点仅 server-id/report_host/local_address 不同)

# 执行节点: 141(142/143 把 server-id 改为 2/3, IP 尾段对应改)
cat > /etc/my.cnf << 'EOF'
[client]
socket = /data/mysql/3306/data/mysql.sock

[mysqld]
basedir = /usr/local/mysql
datadir = /data/mysql/3306/data
user    = mysql
port    = 3306
socket  = /data/mysql/3306/data/mysql.sock
log_error = /data/mysql/3306/data/mysqld.err
log_timestamps = system

# ===== 基础复制参数 =====
server-id = 1                          # 三节点唯一(1/2/3)
log-bin = mysql-bin                    # MGR 强制 binlog
binlog_format = ROW                    # MGR 强制 ROW
binlog_row_image = FULL                # MGR 强制 FULL(8.0 默认)
gtid_mode = ON                         # MGR 强制 GTID
enforce_gtid_consistency = ON
log_slave_updates = ON                 # 组内事务要写回 binlog
master_info_repository = TABLE         # 崩溃安全(8.0 默认TABLE)
relay_log_info_repository = TABLE
relay_log_recovery = ON
report_host = 192.168.195.141          # 组内显示的主机名(关键!否则用主机名解析)
report_port = 3306

# ===== MGR 核心参数 =====
# loose- 前缀: 插件未安装时参数不报错,mysqld 可先正常启动
loose-plugin_load_add = 'group_replication.so'   # 随服务自动加载 MGR 插件
loose-transaction_write_set_extraction = XXHASH64  # write set 提取算法(冲突检测用)
loose-group_replication_group_name = '982e833d-9c5e-4bcb-a36a-d05573d03bb8'  # 组名,三节点一致
loose-group_replication_start_on_boot = OFF      # 不随 mysqld 自动启动组(手动控制,便于演练)
loose-group_replication_local_address = '192.168.195.141:33061'   # 本节点组通信地址
loose-group_replication_group_seeds = '192.168.195.141:33061,192.168.195.142:33061,192.168.195.143:33061'
loose-group_replication_bootstrap_group = OFF    # 引导开关,仅首次手动置 ON
loose-group_replication_single_primary_mode = ON # 单主模式(生产默认)
loose-group_replication_recovery_use_ssl = 0     # 恢复通道不走SSL(实验环境)

# ===== MGR 性能/容错调优 =====
loose-group_replication_communication_stack = XCOM   # 8.0.27+ 通信栈
loose-group_replication_message_cache_size = 1073741824  # 消息缓存 1G(恢复时补偿用)
# loose-group_cache_size = 134217728              # 8.0.26+ 已并入 message_cache_size,注释保留
loose-group_replication_flow_control_mode = 'DISABLED'   # 流控关闭(小集群/低延迟内网)
loose-group_replication_poll_spin_loops = 72       # 通信轮询自旋(默认)
loose-group_replication_compression_threshold = 1000000  # 组播消息压缩阈值 1M
loose-group_replication_exit_state_action = READ_ONLY    # 异常退出时自动只读(安全)
loose-group_replication_member_expel_timeout = 5    # 成员驱逐超时(默认5s,可调大容忍抖动)

# ===== 内存参数(2.8G 小内存机器) =====
innodb_buffer_pool_size = 512M
innodb_redo_log_capacity = 256M
EOF

⚠️ 避坑group_replication_group_seeds 必须包含全部节点(含自己);report_host 强烈建议写 IP,避免主机名解析问题。

4.4 systemd 服务 + 初始化(三节点)

# 执行节点: 141/142/143
cat > /etc/systemd/system/mysqld.service << 'EOF'
[Unit]
Description=MySQL Server (MGR Node)
After=network.target syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
Type=forking
PIDFile=/data/mysql/3306/data/mysqld.pid
TimeoutSec=0
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --pid-file=/data/mysql/3306/data/mysqld.pid --daemonize $MYSQLD_OPTS
EnvironmentFile=-/etc/sysconfig/mysql
LimitNOFILE=65535
Restart=on-failure
RestartPreventExitStatus=1
PrivateTmp=false
EOF
echo 'MYSQLD_OPTS=' > /etc/sysconfig/mysql
systemctl daemon-reload

/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --initialize   # 无输出即成功
grep 'temporary password' /data/mysql/3306/data/mysqld.err   # 取临时密码
systemctl start mysqld && systemctl enable mysqld

4.5 改密码 + 安装插件(三节点)

-- 执行节点: 141/142/143 (用各自的临时密码登录)
ALTER USER user() IDENTIFIED BY 'Root@123456';

INSTALL PLUGIN group_replication SONAME 'group_replication.so';  -- MGR插件
INSTALL PLUGIN clone SONAME 'mysql_clone.so';                    -- clone插件(增量重建用)
SHOW PLUGINS;  -- 两行 ACTIVE 即成功:
-- group_replication  ACTIVE  GROUP REPLICATION  group_replication.so  GPL
-- clone              ACTIVE  CLONE              mysql_clone.so        GPL

4.6 复制用户(三节点,SQL_LOG_BIN=0 防止本地事务污染 GTID)

-- 执行节点: 141/142/143
SET SQL_LOG_BIN=0;   -- 关键!建用户不记 binlog,避免各节点 GTID 不一致
CREATE USER 'repuser'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repuser'@'%';
CREATE USER 'repuser'@'127.0.0.1' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repuser'@'127.0.0.1';
CREATE USER 'repuser'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repuser'@'localhost';
SET SQL_LOG_BIN=1;

-- 配置组恢复通道(新节点加入时经此通道从种子节点补数据)
CHANGE MASTER TO MASTER_USER='repuser', MASTER_PASSWORD='123456'
  FOR CHANNEL 'group_replication_recovery';

五、单主 MGR 组启动(首次引导)

5.1 141 引导组(仅首次!)

-- 执行节点: 141
SET GLOBAL group_replication_bootstrap_group=ON;  -- 打开引导开关
START GROUP_REPLICATION;                           -- 启动组(此刻组里只有自己)
SET GLOBAL group_replication_bootstrap_group=OFF;  -- 立刻关闭!否则重启会分裂成两个组

-- 验证(几秒后):
SELECT MEMBER_HOST, MEMBER_ROLE, MEMBER_STATE FROM performance_schema.replication_group_members;
-- MEMBER_HOST   MEMBER_ROLE  MEMBER_STATE
-- 192.168.195.141  PRIMARY   ONLINE       <- 引导成功

5.2 142/143 加入组

-- 执行节点: 142(143 同理)
START GROUP_REPLICATION;

-- 若报 ERROR 3092 + 错误日志有 "This member has more executed transactions than those
-- present in the group" -> 节点有本地事务(如装插件时记了 binlog),与组 GTID 冲突。
-- 解决(新节点安全操作): 清空本地 GTID 再加入
STOP GROUP_REPLICATION;
RESET MASTER;            -- 清空 gtid_executed 与 binlog(仅对全新节点安全!)
START GROUP_REPLICATION;

5.3 全组上线验证

-- 执行节点: 任意成员
SELECT MEMBER_HOST, MEMBER_ROLE, MEMBER_STATE, MEMBER_VERSION
FROM performance_schema.replication_group_members;
-- 192.168.195.141  PRIMARY    ONLINE  8.0.35
-- 192.168.195.142  SECONDARY  ONLINE  8.0.35
-- 192.168.195.143  SECONDARY  ONLINE  8.0.35   <- 三节点全 ONLINE 即成功

-- 从节点自动进入只读:
SELECT @@read_only, @@super_read_only;  -- 142/143 应为 1/1

5.4 测试数据(主库建,秒级同步)

-- 执行节点: 141 (PRIMARY)
CREATE DATABASE mgr_test;
USE mgr_test;
CREATE TABLE t1 (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  amount DECIMAL(10,2) DEFAULT 0.00,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
INSERT INTO t1(name,amount) VALUES ('订单A',100.00),('订单B',200.50),('订单C',300.75);
CREATE TABLE t2 (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  host_tag VARCHAR(20),
  note VARCHAR(100)
) ENGINE=InnoDB;
INSERT INTO t2(host_tag,note) VALUES ('node141-init','初始数据'),('node141-init','第二条');

-- 执行节点: 142/143 验证(应秒级一致):
SELECT COUNT(*) FROM mgr_test.t1;   -- 3
SELECT COUNT(*) FROM mgr_test.t2;   -- 2

5.5 单主写限制验证

-- 执行节点: 142/143 (SECONDARY)
INSERT INTO mgr_test.t1(name) VALUES ('try-write');
-- ERROR 1290 (HY000): The MySQL server is running with the
-- --super-read-only option so it cannot execute this statement
-- <- 报此错 = 单主模式只读保护生效,验证成功

六、全场景验证实录(12 场景全部通过)

场景1: PRIMARY 故障自动 failover ✅

# 执行节点: 141 (当时 PRIMARY)
systemctl stop mysqld          # 模拟主库宕机
-- 执行节点: 142 (约10~30秒后查询,组检测+选举)
SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 实测结果:
-- 192.168.195.142  PRIMARY    ONLINE   <- 142 自动当选新主
-- 192.168.195.143  SECONDARY  ONLINE

-- 新主写入验证(业务无缝):
-- 执行节点: 142
INSERT INTO mgr_test.t1(name,amount) VALUES ('write-on-new-primary',888.88);
SELECT COUNT(*) FROM mgr_test.t1;  -- 4 (含旧主已同步的全部数据,零丢失)
SELECT @@read_only;                -- 0 (新主可写)

恢复旧主回组(重要:旧主重启后是独立实例,需手动加入):

# 执行节点: 141
systemctl start mysqld
START GROUP_REPLICATION;   -- 141 以 SECONDARY 回归,自动追平差量
SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 141 SECONDARY ONLINE,数据自动同步到最新

场景2: 手动在线切主(group_replication_set_as_primary)✅

-- 执行节点: 当前 PRIMARY (任意成员执行,组内广播)
-- 1.查目标成员 UUID:
SELECT MEMBER_ID FROM performance_schema.replication_group_members
WHERE MEMBER_HOST='192.168.195.141';
-- -> a2c03766-98c0-11f1-8e59-000c29048d1f

-- 2.指定切主:
SELECT group_replication_set_as_primary('a2c03766-98c0-11f1-8e59-000c29048d1f');
-- -> Primary server switched to: a2c03766-... (切换成功)

-- 3.验证:
SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 141 -> PRIMARY, 其余 SECONDARY, 全 ONLINE

场景3: 单主 -> 多主在线切换 ✅

-- 执行节点: 任意成员
SELECT group_replication_switch_to_multi_primary_mode();
-- -> Mode switched to multi-primary successfully.

SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 实测: 三个节点全部 PRIMARY, 全 ONLINE

多主三节点并发写验证(数据最终一致):

-- 执行节点: 141
INSERT INTO mgr_test.t1(name,amount) VALUES ('multi-141',11.11);
-- 执行节点: 142
INSERT INTO mgr_test.t1(name,amount) VALUES ('multi-142',22.22);
-- 执行节点: 143
INSERT INTO mgr_test.t1(name,amount) VALUES ('multi-143',33.33);

-- 三节点分别验证(最终完全一致):
SELECT COUNT(*) rows_all, SUM(amount) total FROM mgr_test.t1;
-- 三节点均为: rows_all=7, total=1556.79  <- 一致性验证成功

场景4: 多主写冲突检测(certification)✅

# 双端同时 INSERT 相同主键(并发脚本):
# 执行节点: 142 后台脚本
cat > /tmp/ins142.sh << "EOF"
#!/bin/bash
M="/usr/local/mysql/bin/mysql -uroot -S /data/mysql/3306/data/mysql.sock -pRoot@123456 mgr_test"
sleep 5   # 等双端就绪,同时开跑
$M -e "INSERT INTO race_t VALUES (8888,\"from142\",NOW(3));"
EOF
# 执行节点: 143 同样脚本(值 from143)
-- 实测结果:
-- 142: 插入成功(先通过组认证)
-- 143: ERROR 1062 (23000): Duplicate entry '8888' for key 'race_t.PRIMARY'
--      <- 后到者在认证阶段被回滚,客户端收到错误。这就是 MGR 冲突检测!

-- 最终全组一致(只有一条 8888):
SELECT id,src FROM mgr_test.race_t WHERE id=8888;   -- from142

-- 认证统计(PDF 监控点):
SELECT COUNT_TRANSACTIONS_CHECKED FROM performance_schema.replication_group_member_stats;
-- 数值持续增长 = 认证器在工作

知识点:冲突在组认证阶段检测(基于 write set 的主键/唯一键比对),后提交者在所有成员上回滚。业务侧应靠"不同节点写不同分片/表"规避冲突,而非依赖回滚。

场景5: 多主模式删节点(STOP GROUP_REPLICATION)✅

-- 执行节点: 143 (主动退出组)
STOP GROUP_REPLICATION;
-- 组内其余成员视角: 143 消失,141/142 继续服务
-- 143 数据停在退出前(502行),后续组内新写不会同步给它

-- 重新加入(数据落后时需先补齐,见场景6):
START GROUP_REPLICATION;

场景6: clone 插件物理重建落后节点 ✅

适用:节点数据落后太多/数据目录损坏,用 clone 从 donor 物理拷贝重建(比 binlog 追平快得多)。

-- 第1步: donor(141) 建 clone 账号
-- 执行节点: 141
SET SQL_LOG_BIN=0;
CREATE USER 'clone_user'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT BACKUP_ADMIN ON *.* TO 'clone_user'@'%';   -- donor 必须 BACKUP_ADMIN
SET SQL_LOG_BIN=1;

-- 第2步: recipient(143) 执行克隆
-- 执行节点: 143
STOP GROUP_REPLICATION;                         -- 先退出组
SET GLOBAL super_read_only=0;                   -- 克隆需要可写(clone报1290时)
SET GLOBAL clone_valid_donor_list = '192.168.195.141:3306';  -- 指定donor白名单
CLONE INSTANCE FROM 'clone_user'@'192.168.195.141':3306 IDENTIFIED BY '123456';
-- 报 ERROR 3707 (Restart server failed) 是正常现象:clone完成后实例自动重启,
-- systemd 管理下 supervisor 不在,需手动: systemctl start mysqld
# 执行节点: 143
systemctl start mysqld   # 完成克隆收尾
-- 验证克隆结果(数据与 donor 完全一致):
SELECT COUNT(*) FROM mgr_test.race_t;  -- 502 (与141一致)
SELECT COUNT(*) FROM mgr_test.t1;      -- 7

-- 重新入组:
START GROUP_REPLICATION;
SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 三节点全 ONLINE

clone 踩坑实录(都写进文档供参考):

  1. Access denied; you need BACKUP_ADMIN -> donor 的 clone 账号缺 BACKUP_ADMIN 权限
  2. ERROR 1290 --super-read-only -> recipient 处于只读,先 SET GLOBAL super_read_only=0
  3. ERROR 3707 Restart server failed (mysqld is not managed by supervisor process) -> systemd 管理的实例克隆后不会自动重启,systemctl start mysqld 即可

场景7: 多主 -> 单主回切 ✅

-- 执行节点: 任意成员(8.0.13+ 不允许 SET GLOBAL 改模式,必须用UDF)
-- 先取目标主 UUID:
SELECT MEMBER_ID FROM performance_schema.replication_group_members
WHERE MEMBER_HOST='192.168.195.141';

SELECT group_replication_switch_to_single_primary_mode('a2c03766-98c0-11f1-8e59-000c29048d1f');
-- -> Mode switched to single-primary successfully.

-- 实测: 直接 SET GLOBAL group_replication_single_primary_mode=ON 会报:
-- ERROR 3093: Cannot modify group replication mode by changing
-- group_replication_single_primary_mode system variable.
-- Please use the group_replication_switch_to_single_primary_mode() UDF

SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 141 PRIMARY, 142/143 SECONDARY, 全 ONLINE

场景8: 选举权重(group_replication_member_weight)✅

-- 执行节点: 143(设为最高权重,期望它当选新主)
SET GLOBAL group_replication_member_weight=100;
-- 执行节点: 142
SET GLOBAL group_replication_member_weight=50;
-- (141保持默认0; 权重只在选举时比较,越大越优先当选)
# 执行节点: 141(当前PRIMARY) 模拟宕机
systemctl stop mysqld
-- 执行节点: 142 视角(约30秒后):
SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 实测: 143(weight=100) 当选 PRIMARY, 142(weight=50) 仍 SECONDARY
-- <- 权重选举生效,验证成功!

权重是选举建议而非绝对:若高权重节点数据落后(未追平),组仍会选数据最全的成员,防丢数据优先。

场景9: 网络分区/脑裂防护(多数派 vs 少数派)✅

# 执行节点: 143(当时PRIMARY) 用 iptables 隔离自己的组通信端口
iptables -A INPUT  -p tcp --dport 33061 -j DROP
iptables -A OUTPUT -p tcp --dport 33061 -j DROP
-- 约40秒后,多数派(141+142)视角:
-- 执行节点: 141
SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 实测: 141 自动当选新 PRIMARY,143 被踢出视图(141/142 ONLINE)

-- 少数派(143)视角(脑裂现场!):
-- 执行节点: 143
SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 141/142 显示 UNREACHABLE,143 仍自认 PRIMARY,@@read_only=0

-- 关键验证: 少数派写入无法提交!
-- 执行节点: 143
INSERT INTO mgr_test.t1(name) VALUES ('minority-write');
-- 实测: 语句卡住(等多数派认证,永不可能达成),超时被杀后事务仍在 RUNNING:
SELECT trx_state FROM information_schema.innodb_trx;  -- RUNNING(悬挂)
-- <- 这就是 MGR 脑裂防护: 少数派"看似主库"但写不进任何数据
# 解除隔离(执行节点: 143)
iptables -D INPUT  -p tcp --dport 33061 -j DROP
iptables -D OUTPUT -p tcp --dport 33061 -j DROP
-- 约30秒后自动收敛(无需人工干预):
-- 执行节点: 143
SELECT MEMBER_HOST,MEMBER_ROLE,MEMBER_STATE FROM performance_schema.replication_group_members;
-- 实测: 143 自动降级 SECONDARY(read_only=1),数据自动追平(8行与多数派一致)
-- 少数派期间的悬挂事务被回滚,零数据分裂  <- 自愈完整闭环!

场景10: flow control 流控与监控视图 ✅

-- 执行节点: 141
SHOW VARIABLES LIKE 'group_replication_flow_control%';
-- 关键参数:
--   flow_control_mode = DISABLED            (本环境关闭;生产默认ADAPTIVE)
--   flow_control_applier_threshold = 25000  (applier队列超此值触发流控)
--   flow_control_certifier_threshold = 25000(认证队列阈值)
--   flow_control_hold_percent/release_percent: 流控时暂停/恢复的吞吐比例

-- 成员事务统计(核心监控表):
SELECT MEMBER_ID,
       COUNT_TRANSACTIONS_IN_QUEUE,              -- 认证队列(积压告警点)
       COUNT_TRANSACTIONS_CHECKED,               -- 已认证事务数
       COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE, -- 远程applier积压(延迟告警点)
       COUNT_TRANSACTIONS_REMOTE_APPLIED         -- 已应用远程事务
FROM performance_schema.replication_group_member_stats;

场景11: 从库网络闪断自愈 ✅

# 执行节点: 142 (SECONDARY) 隔离30秒再恢复
iptables -A INPUT -p tcp --dport 33061 -j DROP
iptables -A OUTPUT -p tcp --dport 33061 -j DROP
sleep 35
iptables -D INPUT -p tcp --dport 33061 -j DROP
iptables -D OUTPUT -p tcp --dport 33061 -j DROP
-- 实测时间线:
-- T+35s: 141视角 142 被踢出(只剩141/143,多数派仍存活,服务不中断)
-- T+65s: 142 网络恢复后自动重连回组,SECONDARY ONLINE,数据自动追平(8行)
-- 全程主库服务不中断,无需人工干预  <- MGR 健壮性实证

场景12: 全组 GTID 一致性核验 ✅

-- 执行节点: 141/142/143 分别执行,比对输出必须完全一致
SELECT @@gtid_executed;
-- 实测三节点输出:
-- 982e833d-9c5e-4bcb-a36a-d05573d03bb8:1-20:1000006-1000543:2000007-2000040,
-- a2c03766-98c0-11f1-8e59-000c29048d1f:1
-- (含多主阶段历史 + VIEW变更事件,三节点逐字节一致 = 组一致性健康)

七、日常管理命令速查(MGR 运维必背)

7.1 组状态监控

-- 成员视图(最常用,健康检查第一入口)
SELECT MEMBER_HOST, MEMBER_ROLE, MEMBER_STATE, MEMBER_VERSION
FROM performance_schema.replication_group_members;

-- 成员事务统计
SELECT * FROM performance_schema.replication_group_member_stats\G

-- 组通信信息(视图ID/所有权)
SELECT * FROM performance_schema.replication_group_communication_information\G

-- 连接状态(恢复通道/applier通道)
SELECT * FROM performance_schema.replication_connection_status
WHERE CHANNEL_NAME LIKE 'group%';
SELECT * FROM performance_schema.replication_applier_status
WHERE CHANNEL_NAME LIKE 'group%';

7.2 成员管理

START GROUP_REPLICATION;             -- 加入组
STOP GROUP_REPLICATION;              -- 退出组(数据保留)
SET GLOBAL group_replication_bootstrap_group=ON;   -- 引导组(仅首次,用完立即OFF)

7.3 模式切换(8.0.13+ UDF)

SELECT group_replication_switch_to_multi_primary_mode();          -- 单主->多主
SELECT group_replication_switch_to_single_primary_mode();         -- 多主->单主(自动选主)
SELECT group_replication_switch_to_single_primary_mode('uuid');   -- 多主->单主(指定主)
SELECT group_replication_set_as_primary('uuid');                  -- 单主下手动指定切主

⚠️ 8.0.13 起禁止 SET GLOBAL group_replication_single_primary_mode 直接改(ERROR 3093),必须用 UDF 在线切换。

7.4 MGR 相关重要变量

SHOW VARIABLES LIKE 'group_replication%';
-- 选举与超时:
--   group_replication_member_weight           选举权重(越大越优先当选)
--   group_replication_member_expel_timeout    驱逐超时(默认5s)
--   group_replication_unreachable_majority_timeout  少数派超时退出(默认0不退,生产建议设)
--   group_replication_exit_state_action       异常退出动作(READ_ONLY/ABORT_SERVER)
-- 流控:
--   group_replication_flow_control_mode       DISABLED/ADAPTIVE(生产默认)
-- 恢复:
--   group_replication_recovery_use_ssl        恢复通道SSL
--   clone_valid_donor_list                    clone donor白名单

八、常见故障与排错(实测踩坑汇总)

8.1 新节点加入报 ERROR 3092(本地 GTID 多于组)

ERROR 3092: The server is not configured properly to be an active member of the group.
错误日志: This member has more executed transactions than those present in the group.

原因:新节点有本地事务(装插件/建用户时未 SET SQL_LOG_BIN=0,记入了 binlog),组拒绝接纳来路不明的事务。
解决(全新节点安全):STOP GROUP_REPLICATION; RESET MASTER; START GROUP_REPLICATION;
预防:所有"管理性质"SQL(建用户/授权/装插件)前先 SET SQL_LOG_BIN=0

8.2 clone 报权限/只读错误

报错原因解决
Access denied; BACKUP_ADMINdonor 端 clone 账号缺权donor: GRANT BACKUP_ADMIN ON *.* TO clone_user
ERROR 1290 super-read-onlyrecipient 处于只读recipient: SET GLOBAL super_read_only=0
ERROR 3707 Restart failedsystemd 下无 supervisorsystemctl start mysqld 手动拉起

8.3 ERROR 3093 模式切换被拒

ERROR 3093: Cannot modify group replication mode by changing
group_replication_single_primary_mode system variable.

原因:8.0.13+ 禁止 SET GLOBAL 改模式。
解决:用 UDF(见 7.3)。

8.4 成员长时间 UNREACHABLE

排查group_replication_local_address 端口(默认33061)网络连通性;member_expel_timeout 是否设得过大;对端 mysqld 存活。
处置:网络恢复后组自动收敛(场景9/11 实证);若节点确定报废,多数派继续服务,节点用 clone 重建(场景6)。

8.5 少数派悬挂事务

现象:分区期间少数派的写事务卡 RUNNING 不返回。
原理:事务需多数派认证,分区下不可能达成,只能等超时或分区恢复。
预防:设 group_replication_unreachable_majority_timeout(如30s),少数派主动退出组转只读,客户端快速失败重定向到多数派 VIP。


九、部署检查清单(复现路线图)

步骤操作节点验证点
1清理旧环境三节点无 mysqld 服务/进程/目录
2下载+分发二进制包141->全md5 一致 (c17075cfc58d8cd25cea4be36d77eed2)
3建用户/解压/软链三节点mysql --version = 8.0.35
4写 /etc/my.cnf三节点server-id 唯一,组名/seeds 一致
5systemd 服务+初始化三节点错误日志出现临时密码
6改密+装两插件三节点SHOW PLUGINS 两行 ACTIVE
7repuser+恢复通道三节点mysql.user 3 条 repuser
8141 引导组141PRIMARY ONLINE
9142/143 加入142/143(3092 则 RESET MASTER) 三节点全 ONLINE
10建测试库表141142/143 秒级同步
1112 场景验证按209章全部通过 ✅

十、环境现状快照(2026-08-16 00:05)

集群模式: 单主 (141=PRIMARY, 142/143=SECONDARY, 全 ONLINE)
GTID: 三节点一致
测试库: mgr_test (t1=8行, t2=2行, race_t=503行, conflict_t=1行)
组名: 982e833d-9c5e-4bcb-a36a-d05573d03bb8
节点 UUID: 141=a2c03766-98c0-11f1-8e59-000c29048d1f
          142=a416e0e7-98c0-11f1-8379-000c29a59955
          143=a5681ae0-98c0-11f1-a06d-000c29c39241
选举权重: 143=100, 142=50, 141=0 (运行时SET,重启失效)
MySQL root 密码: Root@123456 (三节点)
repuser/clone_user 密码: 123456

本笔记所有命令均为实测执行,输出为真实回显。可按"部署检查清单"逐步复现完整环境。
PDF 未覆盖但生产必知:MGR 不处理"客户端如何找到新主"(需 VIP/ProxySQL/Router 配合,参考 MHA/Orchestrator 笔记同理)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值