Hyperf MySQL断线重连需提前识别僵尸连接并安全重建,核心是启用heartbeat心跳检测(如30秒)与设置max_idle_time(如60秒,须小于MySQL wait_timeout)协同,配合wait_timeout和PDO::ATTR_TIMEOUT防卡死,禁用手动reconnect。

Hyperf 的 MySQL 断线重连不能靠“自动重试连接”这种简单逻辑实现,因为协程连接池复用的是底层 TCP 连接,而 MySQL 主动断开(如 `2006 MySQL server has gone away`)后,连接对象在 PHP 层仍存在,只是已失效。真正有效的做法是:**提前识别僵尸连接 + 快速剔除 + 安全重建**,核心靠心跳检测与连接池参数协同。
启用 heartbeat 心跳探活
这是防止复用失效连接的第一道防线。必须显式配置,且值要合理:
-
设为正整数(单位:秒),例如
'heartbeat' => 30,表示每 30 秒检查一次空闲连接是否存活(发 PING 包) - 不能设为 -1 或 0,否则禁用心跳;也不能设太小(如 5),会增加 MySQL 压力并误判
- 该配置位于
config/autoload/db.php对应数据库的pool下,不是全局开关
配合 max_idle_time 强制回收空闲连接
heartbeat 只检测,不清理;max_idle_time 才真正决定连接生命周期:
-
必须显式设置,推荐
'max_idle_time' => 30.0(单位:秒) - 该值需 小于 MySQL 服务端的
wait_timeout(建议设为 300–600 秒),否则连接大概率被 MySQL 先关掉,再复用就报 2006 - heartbeat 值必须 小于 max_idle_time(如 heartbeat=30、max_idle_time=60),否则检测没机会触发
调优 wait_timeout 和 ATTR_TIMEOUT 防卡死
避免协程因等待连接或执行慢查询而挂起:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
-
'wait_timeout' => 5.0:协程最多等 5 秒获取空闲连接,超时直接报错,不排队阻塞 -
PDO::ATTR_TIMEOUT => 3:PDO 层 prepare/execute 操作最多耗时 3 秒,防单条 SQL 卡住整个连接 - 若用 Swoole 原生驱动,还需额外配
'read_timeout' => 5.0和'write_timeout' => 5.0
不推荐的手动重连写法
不要在业务代码里 try-catch 后手动 new PDO 或 DB::reconnect():
- 协程连接池中每个连接绑定到特定协程上下文,手动新建会破坏绑定,易引发 2006 或连接泄露
- DB::transaction() 内部也不要调
$pdo->beginTransaction(),那会绕过连接池管理 - 重试逻辑应封装在 AOP 或装饰器层,而非每个 DAO 方法里硬编码










