大家好,我是数据库小学妹👋我踩过的坑,你别再踩。
上周三凌晨三点零二分,主库10.0.0.1无响应,MHA自动切换,32秒后新主库上线,应用重连恢复。切换很成功,但我盯着监控屏却高兴不起来。因为心里清楚,MHA这个支撑了主从十年的工具,已经停止社区维护近十年了。这次顺利,不代表下次也顺利。所以我做了一个决定:把高可用从MHA升级到InnoDB Cluster。这篇记录完整的升级路径,给你一条能照着走的路线。
为什么必须升级
先说清MHA的现状,这是决定升级的根本原因。
MHA的作者2016年就停止了社区维护,近十年无人更新。官方最新版只支持到MySQL 5.6,5.7兼容性差,在8.0上基本跑不起来。它的binlog解析逻辑不兼容GTID模式下的event位置计算,配置里开gtid_mode根本跑不通,只能走传统位点模式。8.0默认用caching_sha2_password认证,MHA的Perl客户端也不支持。
2026年的社区调研更直接:还用MHA做主要高可用方案的企业只剩12%,用InnoDB Cluster或Group Replication的超过45%。切换速度也被甩开,MHA的32秒在InnoDB Cluster的秒级切换面前,明显落后了。
一句话:MHA不是不能用的工具,但它已经不适合2026年的新需求。存量5.6/5.7系统可以继续靠它撑着,新项目、要长期维护的系统,必须换。
目标方案:InnoDB Cluster是什么
InnoDB Cluster是MySQL官方的高可用方案,由三个组件组成:Group Replication组复制负责数据一致和自动选主,MySQL Router负责应用流量路由,MySQL Shell负责集群管理。
它和MHA的根本区别在一致性模型。MHA是异步复制,主库宕机时靠binlog补偿去追最后几个事务,是"尽力不丢"。InnoDB Cluster是组复制,写入要多数派节点确认才算成功,主库挂了从库本来就有全部数据,是"本来就不丢"。这个区别决定了切换速度:MHA要补日志、漂VIP,InnoDB Cluster靠协议自动选主,通常10秒内完事。
升级前评估
我旧架构是MHA一主两从加VIP,MySQL 5.7。升级方案我选了全新搭建InnoDB Cluster,不动线上,最后再切换。原因很简单:MHA的主从是异步复制,和组复制的协议不能直接混用,原地改造风险高,全新搭建最可控。
评估清单三件事。第一,新集群要三台MySQL 8.4 LTS实例。MySQL 8.0已经在2026年4月EOL,停止安全更新,新搭的集群别再选它,8.4 LTS是官方当前维护的长期支持版。组复制是多数派确认,三节点才安全。第二,三台要同机房,组复制对网络延迟敏感,跨机房延迟高了容易触发多数派失败。第三,迁移要一个停机窗口,因为要停写导数据,提前和业务对好时间。
全新搭建集群
先装MySQL Shell,这是InnoDB Cluster的管理工具。
# 安装 MySQL Shell
yum install mysql-shell
# 连接第一个实例
mysqlsh --uri root@10.0.0.4:3306 --password
进入Shell后配置实例。dba.configureInstance会检查并设置组复制需要的参数,比如binlog、GTID、二进制日志这些,一条命令自动搞定。
// 配置实例(三台都执行)
dba.configureInstance('root@10.0.0.4:3306', {
password:'xxx'});
// 用第一台创建集群
dba.createCluster('mycluster');
// 输出: Cluster successfully created
// 查看集群状态
cluster.status();
创建集群后,把另外两台加入。addInstance会自动处理数据同步,新成员会从主节点拉数据。
// 加入第二、三台实例
var cluster = dba.getCluster('mycluster');
cluster.addInstance('root@10.0.0.5:3306', {
password:'xxx'});
cluster.addInstance('root@10.0.0.6:3306', {
password:'xxx'});
// 确认三节点在线
cluster.status();
看到三个节点都是ONLINE,集群就建好了,这时候它还是空的,下一步导数据。
数据迁移
把旧主库的数据全量搬到新集群。用mysqldump导出,停写之后执行。如果业务实在没法完全停写,--single-transaction在InnoDB表上能拿到一致性快照,配合--master-data可以做在线迁移,只是升级窗口完全停写最安全。
# 旧主库全量导出
mysqldump --single-transaction --master-data=2 \
--all-databases --routines --triggers > /tmp/full.sql
# 导入新集群主节点
mysql -h 10.0.0.4 -uroot -p < /tmp/full.sql
导入完必须校验。先对数量,每个库每张表行数两边比一遍;再抽几张大表做checksum,确认字节级一致。这一步漏了,后面切过去才发现数据差,就晚了。
应用切换:Router替代VIP
MHA时代应用连VIP,VIP挂在哪台,流量就在哪台。InnoDB Cluster不用VIP,用MySQL Router做路由。Router自动感知主节点,主库切换后流量自动跟着走,应用不用改连接,只改一次连接串。
# 在应用侧或独立节点装Router
yum install mysql-router
# bootstrap自动生成配置
mysqlrouter --bootstrap root@10.0.0.4:3306 --user=mysqlrouter
# 启动Router
systemctl start mysqlrouter
Router默认监听两个端口:6446是读写,走主节点;6447是只读,走从节点。应用连接串从旧的VIP改到Router地址,切换就完成了。
# 应用连接示例:读写走6446
mysql -h 10.0.0.100 -P 6446 -uroot -p
验证与下线
先让新旧两套并行跑几天。观察Router路由正常、写入能同步、没有报错,再动旧的。确认无误后,停掉MHA Manager进程,移除VIP脚本和对应的定时任务,旧主从就正式退休了。
验证期间盯三样东西:Router的读写路由是否稳定,新集群三个节点的延迟是否均衡,应用侧有没有连到旧库的残留连接池。三天没有异常,才算迁移完成。
避坑清单
组复制的强一致是多数派确认,写入要等多数节点返回,网络抖动直接拖慢写入。所以三台实例必须同机房,别图省事跨机房部署,延迟一高就频繁触发多数派失败。
MySQL Router本身成了新的单点,它挂了应用就连不上数据库。官方推荐把Router部署在应用所在的主机上,每个应用实例配自己的Router,天然避免单点,还能降低网络延迟。别让Router单独一台孤零零地跑,那等于把单点从数据库换到了Router。
数据迁移要一个干净停机窗口。停写、导出、导入、校验,一气呵成,别边写边迁。位点追不平,导入的数据就比旧库少,切过去才发现就晚了。
三节点是安全线,别因为省钱降到两节点。两节点组复制丢一个,就没了多数派,写入直接阻塞。高可用方案省节点,等于把风险又请了回来。
总结
从MHA到InnoDB Cluster,表面看是换了个工具,本质是换了一套高可用理念。MHA用binlog补偿追求"尽力不丢",InnoDB Cluster用组复制做到"本来就不丢";MHA靠VIP漂移,InnoDB Cluster靠Router自动路由;32秒到秒级,差距就在这。升级不难,全新搭建加数据迁移,难点在评估、校验、验证这三步别省。MHA陪了主从十年,是时候让它退休了。
我是数据库小学妹,帮你少走弯路少踩坑,咱们下篇见👋