MySQL MGR从零搭建指南:高可用数据库的“组队”玩法
写作背景:MySQL用传统的主从比较麻烦,用MGR可以一次性搞定。
一、MGR是什么?能解决什么问题?
MGR(MySQL Group Replication)是MySQL官方推出的组复制方案,说白了就是把多台MySQL服务器组成一个“小团队”,数据在团队成员之间实时同步,有人挂了也不影响业务 。
传统主从复制有哪些坑?
以前我们做高可用,基本就是主从复制那一套:
| 问题 | 表现 | 后果 |
|---|---|---|
| 复制延迟 | 从库数据落后主库 | 读写分离读到旧数据 |
| 主库挂了 | 需要手动选主、切换 | 业务中断几分钟起 |
| 数据不一致 | 主从数据对不上 | 切换后丢数据或错乱 |
| 脑裂 | 两个库都以为自己是主 | 数据写花了 |
MGR就是来填这些坑的 。
MGR的核心优势
-
数据强一致性:事务提交前,必须经过多数派节点确认(Paxos协议),保证数据不丢、不乱
-
自动故障切换:主节点挂了,集群自动选新主,RTO通常在30秒内
-
多节点写入(可选):支持多主模式,所有节点都能写(但有冲突风险,慎用)
-
弹性扩缩容:节点加入或退出,集群自动感知、重新配置
什么时候用MGR?
推荐场景 :
-
金融交易、电商订单等核心业务(对数据一致性要求高)
-
SaaS多租户平台(需要高可用+数据隔离)
-
跨机房部署(需要强同步复制)
不推荐场景:
-
单表日增量>1TB(大事务会拖垮集群)
-
跨公网部署(网络延迟高,性能下降明显)
-
业务有大量无主键表(MGR强制要求主键)
单主模式 vs 多主模式
我的建议:除非你是高手,否则只用单主模式 。
| 模式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 单主 | 一个节点可写,其他只读 | 稳定、冲突少、好管理 | 写入有瓶颈 |
| 多主 | 所有节点都能写 | 扩展写能力 | 冲突检测复杂,网络抖动就炸 |
阿里云官方文档都明确说:“多主模式下集群的稳定性很差,任意节点的抖动或故障,都会影响整个集群的可用性” 。所以下面我只讲单主模式。
二、从零搭建三节点MGR集群(单主模式)
环境规划
三台服务器(CentOS/Rocky/Ubuntu都行):
| 节点 | IP地址 | 主机名 | 角色 |
|---|---|---|---|
| 节点1 | 192.168.1.10 | mgr01 | 初始主节点 |
| 节点2 | 192.168.1.11 | mgr02 | 从节点 |
| 节点3 | 192.168.1.12 | mgr03 | 从节点 |
MySQL版本:8.0.22+(太老的版本有bug,建议用最新稳定版)
第一步:环境准备(三台都做)
1. 配置主机名解析
cat >> /etc/hosts << EOF
192.168.1.10 mgr01
192.168.1.11 mgr02
192.168.1.12 mgr03
EOF
2. 关闭防火墙或放行端口
MGR需要两个端口:
-
3306:MySQL服务端口
-
33061:MGR内部通信端口
# 简单粗暴关防火墙(生产环境建议只放行端口)
systemctl stop firewalld
systemctl disable firewalld
# 或者只放行端口
firewall-cmd --permanent --add-port=3306/tcp
firewall-cmd --permanent --add-port=33061/tcp
firewall-cmd --reload
第二步:安装MySQL(三台都做)
1. 添加MySQL官方yum源
# CentOS/Rocky
yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
# Ubuntu
wget https://dev.mysql.com/get/mysql-apt-config_0.8.24-1_all.deb
dpkg -i mysql-apt-config_0.8.24-1_all.deb
apt update
2. 安装MySQL
yum install -y mysql-server
3. 初始化并启动
systemctl start mysqld
systemctl enable mysqld
# 查看初始密码
grep 'temporary password' /var/log/mysqld.log
# 输出类似: root@localhost: h<GL%Lr:v66W
4. 修改root密码并配置基础参数
mysql -uroot -p'初始密码'
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的强密码123!';
第三步:配置MGR参数(三台都做)
编辑 /etc/my.cnf,在 [mysqld] 段下添加以下配置:
# 基础复制配置
server_id = 1 # 节点1设为1,节点2设为2,节点3设为3
gtid_mode = ON
enforce_gtid_consistency = ON
binlog_format = ROW
binlog_checksum = NONE
log_slave_updates = ON
log_bin = binlog
relay_log_info_repository = TABLE
master_info_repository = TABLE
# MGR核心配置
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" # 所有节点相同
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "192.168.1.10:33061" # 节点1写自己IP
loose-group_replication_group_seeds = "192.168.1.10:33061,192.168.1.11:33061,192.168.1.12:33061"
loose-group_replication_bootstrap_group = OFF
loose-group_replication_single_primary_mode = ON # 单主模式
loose-group_replication_enforce_update_everywhere_checks = OFF
# 其他优化
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
binlog_transaction_dependency_tracking = WRITESET
slave_parallel_type = LOGICAL_CLOCK
slave_parallel_workers = 4
注意:三台服务器的 server_id 和 group_replication_local_address 要分别改成自己的。
改完后重启MySQL:
systemctl restart mysqld
第四步:安装MGR插件(三台都做)
mysql -uroot -p
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
SHOW PLUGINS; -- 看到 group_replication 状态为 ACTIVE 就对了
第五步:创建复制用户(三台都做)
-- 先临时关闭二进制日志记录,避免创建用户的操作被同步
SET SQL_LOG_BIN = 0;
-- 创建MGR内部通信用户
CREATE USER repl@'%' IDENTIFIED BY '你的密码123!';
GRANT REPLICATION SLAVE ON *.* TO repl@'%';
GRANT CONNECTION_ADMIN ON *.* TO repl@'%';
GRANT BACKUP_ADMIN ON *.* TO repl@'%';
GRANT GROUP_REPLICATION_STREAM ON *.* TO repl@'%';
FLUSH PRIVILEGES;
-- 恢复二进制日志
SET SQL_LOG_BIN = 1;
-- 配置复制通道
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='你的密码123!' FOR CHANNEL 'group_replication_recovery';
踩坑提醒:如果提示 super_read_only 相关错误,先执行 SET GLOBAL super_read_only = OFF; 再试 。
第六步:启动MGR集群
先在节点1(主节点)执行:
-- 引导集群(只在第一个节点执行)
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;
-- 查看集群状态
SELECT * FROM performance_schema.replication_group_members;
如果正常,应该看到类似输出:
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | mgr01 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
然后在节点2和节点3(从节点)执行:
START GROUP_REPLICATION;
-- 再次在主节点查看状态,应该三个都是 ONLINE
SELECT * FROM performance_schema.replication_group_members;
第七步:验证集群功能
1. 检查谁是主节点
SHOW VARIABLES LIKE 'read_only';
-- 主节点应为 OFF,从节点应为 ON
2. 测试同步
在主节点创建数据库和表:
CREATE DATABASE test;
USE test;
CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(20));
INSERT INTO t1 VALUES (1, 'mgr test');
在从节点查询:
USE test;
SELECT * FROM t1; -- 应该能看到刚插入的数据
3. 测试只读限制
在从节点尝试写入:
USE test;
INSERT INTO t1 VALUES (2, 'write on slave');
-- 应该报错:ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option
4. 测试故障切换
模拟主节点宕机:
# 在节点1上
systemctl stop mysqld
在节点2或3上查看集群状态:
SELECT * FROM performance_schema.replication_group_members;
-- 会看到节点1状态变成 UNREACHABLE,然后被移除
-- 剩下两个节点中,其中一个会变成新的主节点(read_only变为OFF)
三、日常运维与监控
常用监控SQL
-- 查看所有成员状态
SELECT * FROM performance_schema.replication_group_members;
-- 查看成员统计信息
SELECT * FROM performance_schema.replication_group_member_stats\G
-- 查看各节点事务延迟
SELECT MEMBER_ID, COUNT_TRANSACTIONS_IN_QUEUE, COUNT_TRANSACTIONS_CHECKED
FROM performance_schema.replication_group_member_stats;
添加新节点
-- 在新节点上
-- 1. 配置好my.cnf,server_id唯一
-- 2. 安装插件
-- 3. 创建repl用户
-- 4. CHANGE MASTER TO ...
-- 5. START GROUP_REPLICATION;
删除节点
-- 在要删除的节点上
STOP GROUP_REPLICATION;
-- 如果想彻底清理,可以删除数据目录重新初始化
四、避坑指南
1. 表必须有主键
MGR强制要求所有表必须有显式主键,否则同步会失败。检查无主键表:
SELECT
t.table_schema, t.table_name
FROM
information_schema.tables t
LEFT JOIN information_schema.columns c
ON t.table_schema = c.table_schema
AND t.table_name = c.table_name
AND c.column_key = 'PRI'
WHERE
t.table_type = 'BASE TABLE'
AND t.table_schema NOT IN ('information_schema', 'performance_schema', 'mysql', 'sys')
AND c.table_name IS NULL;
2. 网络必须稳定
MGR对网络延迟非常敏感,实测跨机房延迟超过50ms,性能下降30%以上 。建议同机房部署,用专线。
3. 大事务是杀手
单个事务太大(>100MB)会阻塞整个集群,因为要等所有节点确认。拆分大事务,或者考虑用pt-archiver分批处理。
4. 内存要够
MGR的XCom层会占用额外内存(约1GB),认证信息数组也会占内存。官方建议内存≥8GB,否则容易OOM 。
5. 不建议用多主模式
别问我怎么知道的,网上那些吹多主的文章,写的人自己生产环境都不敢用。单主模式+读写分离,够用了。
五、总结
MGR是MySQL官方给出的高可用答案,核心优势就三点:
-
数据不丢:多数派确认机制
-
切换自动:不用半夜爬起来手动选主
-
运维简单:官方原生支持,不用套一堆外部脚本
适不适合你?
-
如果你的业务对数据一致性要求高(钱、订单、库存),值得上
-
如果只是个人博客、低并发内部系统,传统主从复制也能用
下一步:
-
搭好MGR后,可以搭配 MySQL Router 实现应用端自动读写分离
-
或者直接上 MySQL InnoDB Cluster,官方全套解决方案
1、MySQL Router:读写分离+自动故障转移
它是啥?
一个轻量级中间件(几百KB),部署在应用服务器上(和应用同机部署)。不存数据,只做转发。
有啥用?
-
读写分离:自动识别SQL是读还是写
-
INSERT/UPDATE/DELETE→ 发到主节点 -
SELECT→ 轮询发到从节点
-
-
自动故障转移:主库挂了,Router自动把写请求切到新主,应用只需要重试连接,不用改代码
-
端口隔离:
-
默认6446端口:写请求(连主库)
-
默认6447端口:读请求(连从库)
-
怎么用?
你搭好MGR后,装个Router,执行一条命令让它“认识”你的集群:
mysqlrouter --bootstrap root@你的某个节点IP:3306
Router会自动从集群拉取拓扑信息,生成配置文件,然后你应用里改一下连接IP为Router的地址、端口6446/6447就行。
2、MySQL InnoDB Cluster:官方全家桶
它是啥?
MySQL官方出的一体化高可用解决方案。可以理解为:
text
InnoDB Cluster = MGR(你已搭好的) + MySQL Shell + MySQL Router
有啥用?
-
一键部署:用MySQL Shell几条命令,就能把MGR+Router全配好,不用你手动改那么多配置文件
-
自动运维:
-
添加节点:
cluster.addInstance() -
移除节点:
cluster.removeInstance() -
故障自动切换:MGR负责选主,Router负责切流量
-
-
统一管理:用Shell的
cluster.status()就能看整个集群健康状态
3、现在的状态
已经手动搭好MGR了,其实就相当于InnoDB Cluster的“内核”已经跑起来了。接下来两条路:
-
轻量级方案:只加个Router,实现读写分离+自动切换(半小时搞定)
-
完整方案:用MySQL Shell把现有MGR“纳管”成InnoDB Cluster,以后加节点、做备份都更规范(适合生产环境)
可以先加个Router试试——装个Router,配一下,改应用连接IP,观察读写分离和故障切换效果。跑熟了之后,如果想更规范,再用MySQL Shell把现有集群“转正”成InnoDB Cluster。
结束语:本人写一些笔记记录,以及工作中遇到的一些问题,方便之后重复阅读,每个人的搭建和操作都不一样,但是可以参考一下,感谢您的点击和阅读。
更多推荐



所有评论(0)