news 2026/10/14 17:01:15

手动搭建MySQL MHA高可用架构:从主库宕机到自动切换实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手动搭建MySQL MHA高可用架构:从主库宕机到自动切换实战

1. 为什么手动搭建MHA依然值得学

1.1 从一次主库宕机说起

凌晨两点,监控告警响了,主库连接数直接掉零。当时我们那套业务用的是单点MySQL,没有做任何高可用。运维同学从被窝里爬起来,手动切从库、改配置、重启服务,前后折腾了四十多分钟。那四十分钟里,所有写操作全部失败,订单堆积、用户投诉、客服电话被打爆。事后复盘,问题不在于“有没有备份”,而在于“切换太慢、太依赖人”。

这件事之后我开始认真研究MySQL的高可用方案。市面上方案不少,但MHA(Master High Availability)是我认为最适合中小团队手动搭建、也最能让人真正理解主从切换底层逻辑的一套架构。它不像某些商业方案那样是个黑盒,你能清楚看到每一步在干什么,出了问题也知道从哪儿查。

这篇文章就是把我自己搭MHA的完整过程拆开讲。MHA的核心价值在于:主库挂了之后,能在几十秒内自动完成故障检测、日志补齐、从库提升、其他从库重新指向新主库这一整套动作,把原本需要人工介入几十分钟的活儿压缩到半分钟以内。适合谁看?有一定Linux和MySQL基础、想给自己的业务加一层高可用保障、又不想一上来就上复杂分布式方案的开发和运维同学。小白也能跟,因为我会把每个参数为什么这么配都讲清楚。

1.2 MHA到底解决了什么问题

先把概念说透。MHA是一套由日本开发者维护的开源工具集,它本身不是MySQL的插件,而是运行在管理节点上的一组Perl脚本,配合每个MySQL节点上的agent程序工作。它的工作模式分两块:Manager节点负责监控和决策,Node节点负责执行具体的切换动作。

它解决的核心问题是主库单点故障。传统主从架构里,主库一挂,从库虽然数据还在,但没人告诉应用该连哪儿,也没人把从库提升成新主库。MHA做的事情就是:持续探测主库心跳,一旦发现主库不可达,立刻从所有从库中挑一个数据最全的(通过对比relay log和binlog的位点),把它提升为新主库,然后把其余从库重新挂到新主库下面,最后(可选)尝试拉起原主库作为新从库。

这里有个关键点很多人忽略:MHA能最大程度保证数据不丢。它会在切换前,从宕机主库上(如果SSH还能连上)把还没同步到从库的binlog差异部分抓下来,补到新主库上。这个动作叫“日志补齐”,是MHA区别于简单脚本切换的核心竞争力。当然,如果主库彻底宕机、SSH都连不上,那这部分差异就补不回来了,这也是为什么MHA官方建议配合半同步复制使用。

2. 搭建前的架构设计与环境规划

2.1 节点角色怎么分配

动手之前先把机器规划好,不然后面改来改去很痛苦。我这次用的是四台机器(虚拟机即可),角色分配如下:

角色主机名说明
Manager管理节点mha-manager跑MHA Manager,负责监控和切换
主库mysql-master初始主库,写节点
从库1mysql-slave1候选主库,优先级高
从库2mysql-slave2候选主库,优先级低

为什么Manager要单独一台?因为Manager本身如果和MySQL混部,主库挂了可能把Manager一起带崩,监控就失效了。管理节点必须独立,这是铁律。如果资源紧张,Manager可以和某台从库混部,但绝不能和主库混部。

从库数量建议至少两个。一个从库也能切,但没有冗余,切换后新架构依然脆弱。两个从库的好处是:一个提升为主库,另一个继续做从库,架构立刻恢复成一主一从,还有余量。

2.2 版本选择与依赖清单

版本这块我踩过坑,必须说清楚。MHA对MySQL版本和操作系统都有要求:

  • MySQL:建议5.7或8.0。MHA 0.58版本对8.0支持较好,但要注意8.0默认的caching_sha2_password认证插件MHA可能不认,需要改成mysql_native_password。
  • 操作系统:CentOS 7或Rocky Linux 8都行,我用的是Rocky 8。关键是Perl环境要全,MHA是Perl写的,缺模块会直接报错。
  • SSH互信:Manager到所有Node、Node之间都要配SSH免密。MHA靠SSH来远程执行命令和拷贝binlog,这个不通后面全白搭。

依赖清单我列一下,装的时候一次性搞定:

# 所有节点都需要的依赖 yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch \ perl-Parallel-ForkManager perl-Time-HiRes perl-ExtUtils-MakeMaker \ perl-Data-Dumper perl-Digest-MD5

注意:perl-Parallel-ForkManager这个模块特别容易漏,MHA Manager启动时会用它做并行操作,缺了会报“Can't locate Parallel/ForkManager.pm”。我第一次搭就是卡在这儿,查了半天。

2.3 网络与端口规划

端口方面,MySQL用默认3306,MHA Manager本身不监听端口,它是主动去连MySQL和SSH。但要注意防火墙:Manager要能访问所有Node的3306和22端口,Node之间也要能互相访问3306和22。我图省事直接把内网网段全放通了,生产环境建议按需开放。

主机名解析也要配好,/etc/hosts里把四台机器的IP和主机名对应写上。MHA配置里用主机名比用IP更清晰,切换日志也好读。

3. 主从复制环境的手动搭建

3.1 主库配置与账号准备

MHA是建立在主从复制基础上的,所以第一步得先把一主两从的复制跑通。先改主库的my.cnf:

[mysqld] server-id=1 log-bin=mysql-bin binlog_format=ROW gtid_mode=ON enforce_gtid_consistency=ON log_slave_updates=ON

这里几个参数解释一下。binlog_format=ROW是MHA推荐的,因为行复制在数据一致性上更可靠,切换时位点计算也更准。gtid_mode=ON开启GTID,好处是切换后从库找位点不用再算binlog文件名和position,直接靠GTID自动定位,极大降低切换出错概率。log_slave_updates=ON是给从库用的,让从库也把收到的更新写进自己的binlog,这样从库才能作为候选主库继续向下游同步。

改完重启MySQL,然后创建复制账号和MHA管理账号:

-- 复制账号 CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl_2024#Pass'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; -- MHA管理账号,需要较大权限 CREATE USER 'mha'@'%' IDENTIFIED BY 'Mha_2024#Pass'; GRANT ALL PRIVILEGES ON *.* TO 'mha'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES;

提示:MHA管理账号权限要给足,因为它要执行CHANGE MASTER TO、RESET SLAVE、SET GLOBAL read_only等操作。生产环境可以细化权限,但搭建阶段先给全,跑通再收紧。

3.2 从库配置与复制启动

两个从库的my.cnf类似,只是server-id不同:

[mysqld] server-id=2 # slave1用2,slave2用3 log-bin=mysql-bin binlog_format=ROW gtid_mode=ON enforce_gtid_consistency=ON log_slave_updates=ON read_only=ON

read_only=ON让从库只读,防止误写。但注意这个参数对拥有SUPER权限的用户无效,MHA切换时会临时改这个值,所以别用super_read_only,否则MHA改不动。

配置好后,在两个从库上分别执行:

CHANGE MASTER TO MASTER_HOST='mysql-master', MASTER_USER='repl', MASTER_PASSWORD='Repl_2024#Pass', MASTER_AUTO_POSITION=1; START SLAVE;

MASTER_AUTO_POSITION=1就是启用GTID自动定位。执行完用SHOW SLAVE STATUS\G检查,确认Slave_IO_Running和Slave_SQL_Running都是Yes,Seconds_Behind_Master为0。

3.3 验证复制与SSH互信

复制跑通后,在主库建个测试库写点数据,看从库能不能同步过来。这一步别省,我见过配置看着都对但实际不同步的情况,多半是防火墙或账号权限问题。

SSH互信配置:Manager节点生成密钥,公钥分发到所有Node;同时每个Node也生成密钥,互相分发。简单点可以直接在Manager上对所有节点做免密,Node之间也做。验证方法就是ssh mysql-master不输密码能进去。

# Manager上执行 ssh-keygen -t rsa -N '' for host in mysql-master mysql-slave1 mysql-slave2; do ssh-copy-id $host done

4. MHA Manager与Node的安装配置

4.1 安装MHA软件包

MHA分两部分:Node节点装mha4mysql-node,Manager节点装mha4mysql-node加mha4mysql-manager。官方没有现成的yum源,得下源码包编译或找rpm包。我用的是源码编译,虽然慢点但兼容性好。

# 所有节点装node tar -zxvf mha4mysql-node-0.58.tar.gz cd mha4mysql-node-0.58 perl Makefile.PL make && make install # Manager节点额外装manager tar -zxvf mha4mysql-manager-0.58.tar.gz cd mha4mysql-manager-0.58 perl Makefile.PL make && make install

装完检查一下命令在不在:which masterha_manager、which masterha_check_ssh。这两个命令后面要用。

4.2 编写Manager配置文件

这是整个搭建的核心。在Manager节点上建/etc/mha/app1.cnf:

[server default] manager_workdir=/var/log/mha/app1 manager_log=/var/log/mha/app1/manager.log user=mha password=Mha_2024#Pass ssh_user=root repl_user=repl repl_password=Repl_2024#Pass ping_interval=2 master_binlog_dir=/var/lib/mysql [server1] hostname=mysql-master candidate_master=1 check_repl_delay=0 [server2] hostname=mysql-slave1 candidate_master=1 check_repl_delay=0 [server3] hostname=mysql-slave2 no_master=1

逐项解释。ping_interval=2是每2秒探测一次主库,探测越频繁切换越快,但网络抖动时容易误判,2秒是个平衡点。master_binlog_dir告诉MHA去哪个目录找binlog,路径必须和实际一致,否则日志补齐会失败。

candidate_master=1表示这个节点可以作为候选主库。我给两个从库都设了,但slave1的优先级更高(MHA按配置顺序选)。check_repl_delay=0是关闭复制延迟检查,意思是即使这个从库有延迟也允许它当主库。这个参数有争议:设0切换快但可能丢数据,设1更安全但延迟大时切不了。我建议只在延迟可控的环境设0,否则还是保守点。

no_master=1表示slave2永远不参与主库竞选,纯做从库。这样架构更清晰。

4.3 配置校验与启动

配置写完别急着启动,先用MHA自带的检查工具验证:

# 检查SSH互信 masterha_check_ssh --conf=/etc/mha/app1.cnf # 检查复制状态 masterha_check_repl --conf=/etc/mha/app1.cnf

check_ssh会遍历所有节点两两测试,全绿才行。check_repl会检查主从复制、账号权限、binlog格式等,输出“MySQL Replication Health is OK”才算过。

这两个检查我强烈建议每次都跑。我遇到过check_repl报“binlog format is not ROW”的情况,回头查才发现有个从库的my.cnf没改全。这种问题不检查直接启动,切换时才发现就晚了。

启动Manager:

nohup masterha_manager --conf=/etc/mha/app1.cnf \ --remove_dead_master_conf \ --ignore_last_failover \ > /var/log/mha/app1/manager.out 2>&1 &

--remove_dead_master_conf表示切换后把死掉的主库配置从文件里删掉,避免下次启动报错。--ignore_last_failover是忽略上次的failover记录,否则MHA默认8小时内不重复切换。这两个参数在测试阶段很有用。

5. 故障切换实测与日志解读

5.1 模拟主库宕机

搭好了不测等于没搭。测试方法很简单:在Manager运行状态下,直接把主库的MySQL进程杀掉,或者更彻底点关机。

# 在mysql-master上 systemctl stop mysqld

然后盯着Manager日志/var/log/mha/app1/manager.log。正常的话几秒内就会看到“Ping(SELECT) failed”之类的探测失败记录,接着开始failover流程。

5.2 切换过程逐步拆解

MHA的切换流程大致分这几个阶段,日志里能清楚看到:

  1. 检测阶段:连续多次ping失败后,判定主库宕机。
  2. 日志补齐阶段:尝试SSH连原主库,把差异binlog拷到Manager,再应用到新主库。如果SSH连不上,跳过这步并记录警告。
  3. 选主阶段:从候选从库中选一个,对比GTID或位点,选数据最新的。
  4. 提升阶段:对新主库执行STOP SLAVE、RESET SLAVE ALL、SET GLOBAL read_only=OFF,把它变成可写主库。
  5. 重定向阶段:其余从库执行CHANGE MASTER TO指向新主库,重新启动复制。
  6. 收尾阶段:写failover记录,Manager进程退出(MHA Manager默认切换后自己停掉,需要配合守护脚本重新拉起或手动重启)。

整个流程实测下来,从杀进程到新主库可写,大概20到40秒。比人工快太多了。

5.3 切换后验证与恢复

切换完成后,登录新主库(原来的slave1)确认:

SHOW MASTER STATUS; SELECT @@read_only; -- 应该是0

再登录slave2,SHOW SLAVE STATUS\G确认它已经指向新主库且复制正常。

原主库修好后,可以手动把它重新加入集群作为从库。步骤是:启动MySQL,执行CHANGE MASTER TO指向新主库,START SLAVE。注意原主库上可能有新主库没有的数据(宕机前没同步的),所以重新加入前最好确认数据一致性,或者干脆用备份重建。

注意:MHA切换后Manager进程会退出,这是设计如此。生产环境要用masterha_manager配合systemd或supervisor做守护,让它退出后自动重启,否则第二次故障就没人管了。

6. 常见问题排查与避坑经验

6.1 高频报错速查表

报错信息原因解决
Can't locate Parallel/ForkManager.pm缺Perl模块装perl-Parallel-ForkManager
SSH connection failed互信没配好重新分发公钥,检查authorized_keys权限
binlog format is not ROWbinlog格式不对改my.cnf并重启MySQL
MySQL Replication Health is NOT OK复制断了或账号错查SHOW SLAVE STATUS,核对账号密码
Failed to get master binlogbinlog路径配错核对master_binlog_dir与实际路径
Authentication plugin 'caching_sha2_password'MySQL8认证插件问题改用户为mysql_native_password

6.2 几个容易翻车的细节

第一个坑:SSH互信只配了单向。MHA不仅Manager要连Node,Node之间也要互相连(比如新主库要从原主库拷binlog)。我第一次只配了Manager到Node,切换时报“SSH to mysql-master failed”。后来补全了所有节点两两互信才通过。

第二个坑:GTID和位点混用。如果主从用GTID,MHA配置里也要相应调整,否则切换时位点计算会出错。我建议要么全GTID,要么全位点,别混。

第三个坑:read_only和super_read_only。前面提过,MHA切换要改read_only,如果开了super_read_only,连SUPER用户都写不了,切换会卡住。生产环境如果非要开super_read_only,得在MHA配置里做特殊处理。

第四个坑:Manager单点。MHA Manager本身也是单点,它挂了就没人监控了。生产环境可以考虑用两个Manager做互备,或者用keepalived给Manager做VIP。这个进阶话题以后可以单独聊。

6.3 我的实操心得

搭MHA最耗时的不是配置,而是排查环境问题。我的建议是:先把主从复制跑稳,再装MHA;装完先跑check_ssh和check_repl,两个都过了再启动;启动后立刻做一次切换测试,别等真出事才发现切不了。

另外,MHA的日志非常详细,出问题先看manager.log,里面会告诉你卡在哪一步。我大部分问题都是靠日志定位的,比瞎猜快得多。

还有一点,MHA不是银弹。它能解决主库宕机的自动切换,但解决不了数据延迟导致的丢失(除非配合半同步),也解决不了脑裂(需要额外机制)。把它当成高可用体系里的一环,而不是全部。

最后分享个小技巧:测试切换时,可以用masterha_master_switch --master_state=alive做在线切换,不用真杀进程。这个命令能在主库活着的时候演练切换,对生产环境做维护窗口特别有用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 17:00:38

低功耗继电器选型指南:电池供电设备的功耗陷阱与五大避坑点

去年做一款电池供电的户外阀门控制器时,我在低功耗继电器选型上栽了个大跟头。设备计划装两节CR123A锂电池,续航目标定在一年,每天只需要开关阀门几次。方案评审的时候,同事随手拿了一颗5V继电器过来,说这点负载绝对够…

作者头像 李华
网站建设 2026/10/14 16:59:30

MES与ERP接口设计说明书:文件交互、排他控制与实绩回传避坑指南

简介:面向SAP R/3与制造执行系统(MES)集成场景的接口设计说明书,以MELEBUS-BMAS模板中追加开发的MES I/F程序为核心,适合负责R/3-MES接口设计与联调的实施顾问和开发人员阅读。资源为1个DOC文档,压缩包约17…

作者头像 李华
网站建设 2026/10/14 16:59:28

2026 高校论文抽检新规解读|okbiye 帮你规避抽检风险,守住毕业底线

前言 很多同学认为,论文通过校内盲审,就万事大吉。但每年都有一批毕业生,在校内答辩结束后,遭遇省级论文抽检,论文被判定不合格,面临撤销学位、延期毕业的严重后果。 2026 年各大高校论文抽检机制持续升级…

作者头像 李华
网站建设 2026/10/14 16:59:19

ESP32本地工作台开发:从SDK到高效烧录调试工具

1. 先聊聊:SDK 本身到底缺了什么?1.1 官方 SDK 解决了什么,没解决什么如果你玩过 ESP32,大概率接触过厂商提供的官方 SDK(比如 ESP-IDF),这套东西本身非常能打:编译系统、组件管理、…

作者头像 李华
网站建设 2026/10/14 16:58:59

ESP32本地调试工作台:从SDK到设备管理工具链的完整设计

做硬件产品联调那段时间,我每天面对的就是:SDK 明明提供了全套的 API,设备端代码也写得挺顺,可一旦进入整机调试阶段,问题全跑到“SDK 管不着”的地方去了。日志只能靠串口监视器一屏一屏地刷,姿态数据在命…

作者头像 李华