mha 在 mysql 8.0+ 上基本无法运行,因官方已停止维护,仅支持至 mysql 5.6,存在 mysqlbinlog 格式变更、change master to 语法不兼容、relay_log_purge 不可动态关闭、caching_sha2_password 认证不支持等核心问题。

为什么 MHA 在 MySQL 8.0+ 上基本跑不起来
MHA(Master High Availability)官方早已停止维护,最新版只支持到 MySQL 5.6,对 MySQL 5.7 兼容性差,到了 8.0 几乎必然失败——比如 mysqlbinlog 输出格式变更导致 apply_diff_relay_logs 解析失败,CHANGE MASTER TO 语法升级后 MHA 脚本无法生成合法语句。
常见错误现象:Can't execute the given command because you have an error in your SQL syntax、Unknown variable 'relay_log_purge'、Failed to parse binlog event。
- MySQL 5.7 起默认启用
relay_log_purge=ON且不可动态关闭,MHA 旧逻辑依赖手动关 purge,直接报错 - MySQL 8.0 默认使用
caching_sha2_password认证插件,MHA 的 Perl 客户端不支持,连不上从库 -
mysqlbinlog --base64-output=DECODE-ROWS输出结构变化,MHA 的日志解析器直接 crash
替代方案选型:用什么真正能落地的高可用组合
不要硬扛 MHA,生产环境现在主流是三类轻量可靠方案,按运维复杂度从低到高排序:
-
Orchestrator + VIP/Proxy:Go 写的,原生支持 MySQL 5.7/8.0,自动检测主从拓扑、支持优雅主从切换、Web 界面直观;配合
keepalived绑定 VIP 或直连ProxySQL做读写分离,故障转移通常在 10–20 秒内 -
MySQL Group Replication(MGR)+ Router:MySQL 官方方案,强一致性(基于 Paxos),但要求所有节点开启
binlog_row_image=FULL、gtid_mode=ON,且网络延迟必须稳定低于 100ms,否则容易脑裂 - Percona Orchestrator + Consul:适合已有 Consul 体系的团队,用 Consul 做服务发现和故障通知,避免单点依赖 MHA manager 节点
别碰 MMM 和老版本 Galera(WSREP),前者已废弃,后者在大事务场景下复制延迟飙升,且 8.0 不再支持
如果非要用 MHA,必须改哪几处才能勉强跑通
仅限 MySQL 5.7 临时过渡,且必须打补丁。以下修改缺一不可:
- 把
master_ip_failover脚本里所有CHANGE MASTER TO语句改成兼容 5.7 的写法,例如显式指定MASTER_AUTO_POSITION=0,并删掉已废弃的MASTER_SSL_CAPATH类参数 - 在所有从库上执行:
SET GLOBAL relay_log_purge = OFF(MHA 启动前),否则apply_diff_relay_logs找不到中继日志 - 替换
mysqlbinlog版本:用 MySQL 5.7 自带的,不能混用 8.0 的客户端;并在masterha_default.cnf中显式配置mysql_binlog_path = /usr/bin/mysqlbinlog - 账号权限必须包含
SUPER、REPLICATION SLAVE、REPLICATION CLIENT,且密码不能含特殊字符(Perl DBI 解析会出错)
示例关键配置段:
[server default] user=mha_user password=<code>mha_pass</code> mysql_binlog_path=/usr/local/mysql-5.7/bin/mysqlbinlog repl_user=repl_user repl_password=<code>repl_pass</code>
真实故障切换时最容易被忽略的三个细节
无论用哪种方案,只要没处理好这三点,切换后业务必连不上或丢数据:
-
read_only=1必须在所有从库(含新主)启动后立即生效,否则应用误写从库,后续主从同步直接中断 - 应用连接字符串里的 host 不能写死 IP,得走 DNS 或 VIP;如果用了 ProxySQL,记得提前在
mysql_users表里把新主加进default_hostgroup - 切换完成后立刻检查
SHOW SLAVE STATUS\G的Seconds_Behind_Master和Retrieved_Gtid_Set是否追平,别只看Slave_IO_Running: Yes
最常踩的坑是:以为 failover 完就结束了,其实从库的 read_only 是手动设的,重启 mysqld 后失效;或者 ProxySQL 没 reload 配置,流量还在往旧主发











