MySQL 8.4 上使用社区版 MHA-Go
摘要
- 社区版 MHA-Go(项目仓库名
mha_go,命令为mha,systemd 服务常叫mha-manager)的安装、配置、检查、在线切换与自动 failover - 本文基于
mysql-8.4.11 LTS+mha-go v0.1.4,操作系统使用 Amazon Linux 2023(x86_64);包管理、路径以 AL2023 为准 - 第 0 节先整理相对原版 MHA 的优缺点再动手;原版 Perl MHA 0.58 见 MySql-MHA的构建方法;主从基线见 MySql8.4单节点、主从、双主的构建方法;官方集群方案见 MySQL 8.4 InnoDB Cluster 的构建方法
0.它是什么、适不适合你
MHA-Go 是原版 MySQL MHA 的 Go 重写:继续做「一主多从 + 外部 Manager 选主」,但换成单二进制、YAML 配置、只认 GTID。它不是原版 0.58 的补丁包,命令、配置、RPM 全部不通用。
版本支持(先看清再装)
详细边界与选型背景见 MySql-MHA的构建方法 里「社区版 MHA-Go 的版本边界」。这里只保留动手所需的结论:
| MySQL 版本 | MHA-Go |
|---|---|
| 8.4.x | 主力支持(发布基线) |
| 9.7 ER/EA | 前向兼容;节点配置写 version_series: "9.7" |
| 5.7 / 8.0 / 9.6 | 不支持 |
| 非 GTID(文件位点复制) | 不支持 |
因此:MySql-MHA的构建方法 里的 mysql-8.0.30 + 原版 MHA 不能直接换成 MHA-Go;要先把数据面迁到 8.4 + GTID(或官方支持的 9.7),再部署 Manager。
和原版 MHA、InnoDB Cluster 的取舍
| 原版 MHA 0.58 | MHA-Go | InnoDB Cluster | |
|---|---|---|---|
| 复制模型 | 异步/半同步主从 | 同左,仅 GTID | Group Replication |
| 选主方式 | 外部 Manager | 外部 Manager | 组内自动选主 |
| 部署形态 | Manager + 每台 Node(Perl) | 单二进制,不必每台装 Node | GR + Shell + Router |
| 适合 | 历史 5.7/8.0 存量 | 必须保留传统主从、又已上 8.4/9.7 | 新部署首选 |
新业务优先 MySQL 8.4 InnoDB Cluster 的构建方法。只有应用、运维流程已经绑死「异步一主多从 + VIP/ProxySQL」,才评估 MHA-Go。项目较新,上线前务必做故障演练。
优缺点(选型时先看)
把它理解成:面向 MySQL 8.4 的现代化外部 MHA,不是「MHA 0.58 的简单 Go 翻译」。相对原版,核心路径从「SSH + Node + 解析 binlog/relay-log」转向「SQL 探测 GTID / 复制线程 / 半同步状态」,切换步骤也更结构化。
优点
| 优点 | 说明 |
|---|---|
| 与 8.4 匹配 | 主力目标就是 8.4.x + GTID 单主,避开原版依赖的已删除语句和 Perl 包袱 |
| 部署干净 | 单 Manager 二进制,无 Perl、不强制每台装 Node;YAML 配置;有预编译包和 SHA256SUMS |
| 发现方式现代化 | 用 SQL 看角色、GTID、read_only、复制线程、延迟、半同步,而不是绑死在 mha4mysql-node |
| 流程可审计 | 候选优先级 → fencing → 晋升 → GTID 追平 → writer_endpoint → 校验;switch / failover-execute 支持 --dry-run |
| 写入口抽象清晰 | VIP/Proxy 走 writer_endpoint(含 precheck/verify),与 fencing(旧主还能不能写)分开建模 |
| 有 8.4 集成测试痕迹 | 仓库含 test/integration/mysql84,比只在 README 声称「支持 8.x」更可信一些 |
| salvage 策略显式 | strict / salvage-if-possible / availability-first 把「补不齐就停」还是「继续切」写进配置 |
缺点 / 风险
| 缺点 | 说明 |
|---|---|
| 成熟度不足 | 项目很新,缺少 MHA 0.58 那种多年大规模踩坑史;技术路线新 ≠ 生产验证充分 |
| 版本覆盖窄 | 不支持 5.7 / 8.0 / 9.6,也不支持非 GTID;不能当老 MHA 全场景替代品 |
| 9.7 仅 Partial | 前向兼容轨道,不是和 8.4 同级的发布基线 |
| 默认对「旧主 SQL 突然不可达」偏保守 | 起步常是 salvage-if-possible 且无 SSH salvage;kill -9/断电后若有未传到从库的 GTID,failover 可能中止 |
| Manager 仍是单点 | 默认 local-memory lease 只防同进程并发,防不了双 Manager,也解决不了脑裂 |
| fencing / VIP 要自己做实 | 工具给能力,网络分区、旧主复活继续写、VIP 双活、应用重连都要靠演练 |
| 与 8.4 认证仍有缝 | 切主重建复制时当前实现不自动加 GET_SOURCE_PUBLIC_KEY=1;非 TLS 下 IO 线程可能起不来 |
| 切完仍有运维负担 | 成功 failover 后 manager 会退出;要改 YAML、再拉起监控,并验证旧主如何以从库加回 |
| 生态偏薄 | 案例、排障资料少于 InnoDB Cluster / 云托管 HA;进阶能力要读 full 配置和 operations |
一句话:适合认真评估的是 MySQL 8.4 + GTID 一主多从、又必须保留传统拓扑;不适合老版本 MySQL、非 GTID,或未做网络分区 / VIP / 旧主回加演练就直接挂核心库。能接受三节点 Group Replication 时,仍优先 MySQL 8.4 InnoDB Cluster 的构建方法。
官方资料:
-
快速说明:docs/README_zh.md
-
进阶必读:docs/operations_zh.md(完整字段与流程)
1.节点规划
先按 MySql8.4单节点、主从、双主的构建方法 搭好 一主两从 + GTID,再装 MHA-Go。本文假设:
1 | mha-manager: 10.250.0.91 只跑 mha 二进制与配置(不要和当前主同机) |
-
Manager 需要能访问三台 MySQL 的
3306;默认拓扑发现走 SQL,不强制 Manager 到各库的 SSH。 -
同一时刻只跑一个 manager。 默认 lease 是进程内
local-memory,不是跨进程或跨主机互斥;起两个 manager 防不了脑裂。 -
VIP / 写入口脚本若要用 SSH 漂移地址,再单独配密钥与 sudo,见第 8 节。
-
各机
/etc/hosts或 DNS 能解析主机名更省事,但cluster.yaml里直接写 IP 也可以。
前置检查(每台 MySQL):
1 | SHOW VARIABLES WHERE Variable_name IN ( |
gtid_mode 与 enforce_gtid_consistency 必须为 ON。
2.创建运维账号与复制账号
在当前主库执行一次即可(经 GTID 复制到从库)。管理账号给 MHA-Go 做探测、切主;复制账号给切主后的 CHANGE REPLICATION SOURCE TO 使用。
1 | -- 管理账号:host 用 CIDR,覆盖 Manager 与各 MySQL 节点所在网段 |
上游 README 快速上手仍用这套偏宽的权限列表;更细的动态权限清单见 operations_zh.md。上游示例常用
'mha'@'10.250.%',MySQL 8.4 已弃用 Host 里的%/_通配,生产更建议 CIDR。
从库应保持 read_only=ON 且 super_read_only=ON。MySql8.4单节点、主从、双主的构建方法 的异步主从模板有时不把 super_read_only 写进 my.cnf(防止宕机主库重启后进只读),因此每次 mysqld 或主机重启后,在确认角色后再检查:
1 | -- 只在已确认的从库上执行 |
主库两者都应是 0,从库都应是 1。不要凭旧配置猜测谁是主。
8.4 复制认证:切主后 IO 线程可能起不来
8.4 默认 caching_sha2_password。按 MySql8.4单节点、主从、双主的构建方法,主从之间若未启用 TLS,手工搭从库时要在 CHANGE REPLICATION SOURCE TO 里加 GET_SOURCE_PUBLIC_KEY=1。
写作时(v0.1.4)MHA-Go 重建复制通道时会写 SOURCE_HOST/PORT/USER/PASSWORD 和 SOURCE_AUTO_POSITION=1;只有配置了非 disabled 的 sql.tls_profile 时才会附加 SOURCE_SSL=1,不会自动加 GET_SOURCE_PUBLIC_KEY=1。
因此实验/生产请二选一:
-
推荐:节点间启用 TLS,并在每个节点的
sql.tls_profile写成required(或至少preferred),让切主后的通道走 SSL。 -
继续明文实验:切主或 failover 后立刻在各从库检查
SHOW REPLICA STATUS;若Replica_IO_Running=No且认证失败,手工补:
1 | CHANGE REPLICATION SOURCE TO GET_SOURCE_PUBLIC_KEY=1; |
上线前用一次真实 switch --dry-run 后再做一次真实 switch,确认复制能自动站起来,不要假设工具已经替你处理好了公钥交换。
3.在 Manager 上安装二进制
写作时最新版为 v0.1.4;安装前到 Releases 核对版本号。
1 | sudo mkdir -p /usr/local/soft /etc/mha/secrets |
也可以从源码静态编译(需要 Go 1.25+):
1 | git clone https://github.com/fanderchan/mha_go.git |
本文 systemd 把日志打到 journal,不必单独建
/var/log/mha。若自己改成文件日志,再创建该目录并收紧属主权限。
4.写 cluster.yaml 与密钥文件
起步配置以仓库 examples/cluster-8.4.yaml 为准;VIP、fencing、hooks、SSH salvage、secondary_checks 等见 cluster-8.4.full.yaml 与 operations_zh.md。
1 | sudo tee /etc/mha/cluster.yaml >/dev/null <<'EOF' |
要点:
-
candidate_priority越大越优先被选为新主;上面让db2优先于db3。只读从库用no_master: true;expected_role: observer也可表示观察者角色。 -
密码用
file:引用,不要写进 YAML,也不要放进 systemd 的Environment=。另两种:env:...(临时/容器)、plain:...(仅 demo)。 -
MySQL 9.7 集群把每个节点的
version_series改成"9.7"即可。 -
起步模板故意没有节点
ssh段。 旧主 SQL 已死、又需要补缺失 GTID 时:要么按 full 示例配 SSH salvage(本机mysql客户端、对端mysqlbinlog),要么接受salvage-if-possible中止,要么显式改成availability-first并接受可能丢数。
5.检查复制健康与命令分工
1 | mha check-repl --config /etc/mha/cluster.yaml |
正常时大致如下:
1 | Cluster: app1 mode=mysql-replication-single-primary primary=db1 nodes=3 |
Assessment: OK 之前不要开 manager,也不要做真实 switch。
| 场景 | 用哪个命令 |
|---|---|
| 健康检查 / 监控探针 | check-repl |
| 主库还活着,计划内换主 | switch(可加 --new-primary) |
| 主库已确认死亡,人工触发 | failover-plan / failover-execute(可加 --candidate) |
| 常驻自动切主 | manager |
全局参数(各业务子命令通用):
| 参数 | 说明 |
|---|---|
--config |
配置文件路径(必填) |
--discoverer sql|static |
默认 sql,靠 SQL 发现实时角色 |
--log-level |
debug / info / warn / error |
--log-format |
text 或 json |
--dry-run |
manager / switch / failover-execute 可预演 |
6.在线切换(计划内)
若 mha-manager 已在跑,先停掉再切,避免自动探测与手工 switch 并发(lease 只护当前进程内操作):
1 | sudo systemctl stop mha-manager |
成功后建议顺序:
-
先改
cluster.yaml:新主expected_role: primary,旧主改为replica,并调整candidate_priority。 -
mha check-repl,确认拓扑与配置一致;同时核对各从库SHOW REPLICA STATUS(尤其非 TLS 时的认证)。 -
尽快
systemctl start mha-manager,恢复自动 HA。旧主可以稍后修好,再以从库身份加回配置并check-repl。
省略 --new-primary 时,会按 candidate_priority 等规则选最优从库;生产建议显式指定。
7.故障转移与常驻监控
一次性计划 / 执行
主库仍存活时,failover-plan / failover-execute 往往会阻塞或拒绝——它们面向「主已不可用」的场景。
1 | mha failover-plan --config /etc/mha/cluster.yaml |
普通从库在规划时已不可达,通常不阻断 failover(可用 ignore_fail 降噪);事后把节点修好再加回配置即可,不必非 Clone 不可——GTID 一致时直接改挂常更轻。
用 systemd 跑 manager
1 | sudo tee /etc/systemd/system/mha-manager.service >/dev/null <<'EOF' |
警告⚠️
成功 failover 后 manager 会正常退出(exit 0)。 旧配置里的角色已过期。正确顺序是:先更新 YAML 反映新主 → check-repl → 立刻 systemctl start mha-manager;旧主可以稍后修复再加回。Restart=on-failure 只处理崩溃和非零退出,不会在「成功切主后」带着过期配置自动拉起。
实验室演练建议
-
check-repl为 OK;若要测自动切,先启用并确认只有一个mha-manager。 -
在主库制造故障前写几笔可核对数据。注意:起步配置默认
salvage-if-possible且无 SSH salvage——kill -9 mysqld后若仍有未传到从库的 GTID,manager /failover-execute很可能中止晋升,这是预期行为,不是工具坏了。 -
想练「一定会切」:先把业务写停干净、确认从库已追上,再杀主;或临时改成
availability-first(接受可能丢数);或按 full 示例配好 SSH salvage。 -
观察
journalctl -u mha-manager:成功则更新 YAML、恢复监控;失败则读阻断原因,不要强行多起 manager。 -
应用必须能重连重试;写事务要幂等。
8.写入口(VIP)与 fencing
起步配置里 writer_endpoint.kind: none,MHA-Go 只负责数据库角色切换,不替你改应用连接。
若要用 VIP / Proxy:
-
从
cluster-8.4.full.yaml打开writer_endpoint(kind: vip或proxy),配置command、建议再配precheck_command/verify_command。 -
同时理解 fencing:未配置时,旧主 SQL 可达会做默认
read_onlyfence;旧主完全不可达时靠 salvage 策略决定是否继续。VIP 漂走 ≠ 旧主一定写不进去,直连旧主仍可能脑裂,需要 stonith / 云路由等更强隔离时再加 fencing steps。 -
配合 dbbot 的
mha_go.yml时,可用其生成的mha_ip_failover.sh、受限 SSH 与 sudo;手工环境需保证 VIP 不会双活、ARP 能刷新、脚本失败时策略符合预期。 -
Keepalived / ProxySQL 只解决路由,不能替代 MHA-Go 的晋升逻辑。
9.和半同步、丢数的关系
-
本文起步默认是
salvage-if-possible+ 纯异步:补不齐缺失 GTID 时 failover 中止,一般不会「默默切成功并丢数」。真正「补不齐也继续」的是availability-first。 -
semi_sync.policy: disabled表示 MHA-Go 不把半同步状态纳入健康判断。要半同步时:先按 MySql8.4单节点、主从、双主的构建方法 安装并启用rpl_semi_sync_source/rpl_semi_sync_replica,再把 policy 改成preferred(半同步异常打 warning)或required(异常打 error 并视为不健康)。 -
strict:规划阶段发现缺失事务就阻断,不做 salvage,最保守,也最容易要人工介入。 -
旧主整机不可达、又没有 SSH salvage 时:
salvage-if-possible/strict都可能阻塞自动晋升。
高可用缩短停写,不等于 RPO=0。细节见 MySql8.4单节点、主从、双主的构建方法。
10.日常命令速查
| 子命令 | 作用 |
|---|---|
check-repl |
一次性健康检查 |
manager |
常驻监控;主库确认死亡后自动 failover,成功后退出 |
switch |
计划内在线切换(主仍健康时用;先停 manager) |
failover-plan |
只生成计划;可 --candidate |
failover-execute |
执行故障转移;可 --dry-run / --candidate |
1 | mha version |
11.什么时候别用它
第 0 节「优缺点」里的风险,落到决策上就是下面几条:
-
还在用 MySQL 5.7 / 8.0 / 9.6,或还没开 GTID:用不上 MHA-Go。
-
可以接受三节点组复制:优先 InnoDB Cluster,少维护一套外部 Manager。
-
需要跨机房自动容灾:看 ClusterSet / 云厂商多可用区,不要指望单套异步复制 + MHA-Go 扛地域故障。
-
没做切主演练、应用没有重试与幂等,或未搞清默认 salvage 在无 SSH 时可能中止:不要把自动
manager直接挂生产。 -
需要同时跑多个 manager「互备」:当前默认 lease 做不到,别靠它防脑裂。
常见面试题(收口)
-
原版 MHA 停更后,社区 Go 重写版支持 8.4.x / 9.7,不支持 5.7、8.0、9.6,且只认 GTID。
-
优点是部署干净、SQL/GTID 驱动、dry-run 与
writer_endpoint清晰;缺点是项目新、场景窄、Manager 单点、默认 salvage 偏保守、非 TLS 认证有缝。 -
默认
salvage-if-possible:补不齐就中止;availability-first才是可用性优先、可能丢未复制事务。 -
MHA-Go 解决传统主从的外部选主;InnoDB Cluster 是另一条产品线,新部署优先后者。
-
Manager 单活;成功 failover 后要先改配置再显式拉起;计划内
switch前先停 manager。 -
8.4 非 TLS 切主后可能缺
GET_SOURCE_PUBLIC_KEY,上线前必须验证复制能自动恢复。