hyperf 默认不自动感知 mysql 主从故障或角色变化,连接切换需应用层显式控制或依赖中间件;其 mysql 组件的 write_host 和 read_hosts 为静态配置,不支持动态刷新,无内置 failover 机制,vip 漂移后旧连接仍复用失效节点,必须通过重启进程、清空并重建连接池或更新配置中心来生效。

Hyperf 默认不自动感知 MySQL 主从节点故障或角色变化,连接切换必须由应用层显式控制或借助中间件完成。直接依赖 mysql 驱动的原生连接池无法自动重连新主库,更不会识别 VIP 漂移或 GTID 位点偏移 —— 这是常见踩坑起点。
Hyperf 中配置读写分离连接池的关键参数
Hyperf 的 mysql 组件支持多节点配置,但“主从”只是逻辑标签,不等于自动故障转移:
-
write_host和read_hosts是静态列表,启动后不会动态刷新;即使某节点宕机,连接池仍会尝试重试(受retry_times控制),但不会主动剔除或替换 -
sticky设为true时,事务内所有查询都打到同一节点,但若该节点在事务中途失联,会抛出ConnectionException,而非自动切到备用 -
failover参数不存在 —— Hyperf 官方 mysql 组件不提供内置 failover 机制,别被文档里“支持主从”误导
手动触发主从切换时必须重置连接池
当通过 MHA 或 Orchestrator 完成 MySQL 主从切换后,Hyperf 应用不会自动更新 write_host 地址。必须主动 reload 或重建连接池:
- 调用
$container->get(MySQL::class)->reconnect()仅重连当前连接,不更新配置;无效 - 正确做法是:修改配置文件中
mysql.write_host.host为新主库 IP,再执行php bin/hyperf.php server:restart - 若用 Consul 或 Nacos 管理配置,需监听变更事件,在回调中调用
Hyperf\Pool\PoolFactory::release('mysql')清空旧池,并触发MySQL::make()新建连接池 - 注意:连接池销毁后,正在执行的请求可能因连接中断失败,需配合
try/catch和幂等设计
为什么不能只靠 keepalived + VIP?
VIP 漂移看似透明,但在 Hyperf 场景下极易引发连接复用问题:
- PHP-FPM 进程内 MySQL 连接是长连接,
mysqli或pdo_mysql不会感知底层 IP 变更;旧连接仍发往已下线的老主库地址,导致超时或拒绝连接 - 即使配置了
mysql.connect_timeout=3,超时后也只会重试原地址,而非切换节点 - 真正生效的方案是:VIP 漂移后,强制所有 PHP 进程重启(如通过 systemd restart 或 kill -USR2),或使用 Swoole 的
reload_async触发协程重载 - 更稳妥的做法是绕过 VIP,让 Hyperf 直接连接新主库真实 IP,并在切换脚本中同步更新配置中心
最易被忽略的是连接池的生命周期与配置热加载边界 —— Hyperf 的连接池一旦初始化,就和配置快照绑定,后续配置变更对已存在连接完全无感。任何“自动切换”都必须落在配置推送、进程重启、连接重建这三者之一,缺一不可。











