2006错误本质是MySQL主动关闭空闲连接后Hyperf仍复用该“僵尸连接”;需在config/autoload/db.php中为对应数据库显式配置heartbeat=>30、max_idle_time=>30.0、wait_timeout=>5.0及PDO::ATTR_TIMEOUT=>3协同生效。

Hyperf 连接 MySQL 报 2006 错误(MySQL server has gone away),本质不是网络断开,而是连接被 MySQL 主动关闭后,Hyperf 还把它当有效连接复用。这在低频请求后突增流量、容器重启、RDS 故障转移等场景下特别常见。
根本原因:空闲连接超时未清理
MySQL 服务端默认或运维设置了较短的 wait_timeout(常为 300–600 秒),而 Hyperf 的 MySQL 连接池默认不主动检测连接是否存活。协程从池中取出一个闲置超时的连接,MySQL 已经悄悄关掉它,但 Hyperf 不知道——一发查询就触发 2006。
- 错误日志只显示
PDOException: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away,不提示连接来源 - 不是“连不上”,而是“连上了却用不了”
- 高频发生在冷启动后第一个请求、定时任务唤醒、或 Redis/MySQL 混用时上下文污染后
关键配置:heartbeat 必须显式启用并协同设置
pool.heartbeat 不是开关,而是检测周期(单位:秒)。它只对空闲连接生效,且必须配合 max_idle_time 才能起作用。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
-
'heartbeat' => 30:每 30 秒对池中闲置连接发一次PING探活 -
'max_idle_time' => 30.0:连接空闲满 30 秒强制回收(必须略小于 MySQL 的wait_timeout) -
'wait_timeout' => 5.0:协程等待空闲连接的最长时间,防排队雪崩 -
'options' => [\PDO::ATTR_TIMEOUT => 3]:PDO 层执行超时,避免慢查询拖垮连接
配置位置在 config/autoload/db.php 对应数据库的 pool 项下,每个库需单独配,不能写在全局。
验证是否生效:别只看日志有没有 heartbeat 字样
真正起效的表现是:错误明显减少、冷请求不再必爆 2006、连接池中“僵尸连接”被提前剔除。
- 可临时加日志,在连接归还前打印
$connection->getAttribute(\PDO::ATTR_CONNECTION_STATUS)辅助判断 - 观察 MySQL 的
Aborted_clients状态变量是否下降(说明无效连接没再被错误复用) - 用
SHOW PROCESSLIST查看活跃连接数是否稳定,而非持续堆积又断开
额外注意:DB::timeout() 不管用
DB::timeout(5) 只对 Query Builder 链式调用(如 DB::table()->where()->get())生效。若你用的是 DB::select()、原生 PDO 或 Swoole MySQL 驱动,这个 timeout 完全无效。
- 真正可控的超时来自三处:MySQL 的
MAX_EXECUTION_TIMEhint(仅 SELECT)、PDO 的ATTR_TIMEOUT、Swoole 驱动的read_timeout -
MAX_EXECUTION_TIME要生效,还需会话有PROCESS权限,且不能卡在锁等待中 - 生产环境建议统一靠
ATTR_TIMEOUT+heartbeat组合兜底,更稳定可靠

















