Hyperf高并发下数据库连接泄漏本质是“借了没还”,需分三步排查修复:先通过SHOW PROCESSLIST和ss命令确认泄漏现象,再聚焦手动获取未释放、事务未兜底、闭包持有等代码问题,最后启用leak_detection_threshold、调优min/max_connections等配置并监控验证。

Hyperf 高并发下数据库连接泄漏不是配置调大就能解决的事,核心在于“借了没还”——连接被取走后因异常、遗漏或设计缺陷没归还池子,导致可用连接越来越少,最终触发 Too many connections 或响应缓慢。排查要分三步走:确认现象、定位代码、修复机制。
看现象:先区分是真泄漏还是配置不足
别一看到连接数高就改 max_connections。先验证是不是泄漏:
- 执行
SHOW PROCESSLIST查看 MySQL 当前活跃连接,重点关注状态为Sleep且Time持续增长(如 > 60s)的连接——这些很可能是被卡住未释放的 - 在容器内运行
ss -s | grep ESTAB,对比结果与配置中pool.max_connections值:若 ESTABLISHED 长期接近甚至等于最大值,且随运行时间持续上涨,基本就是泄漏 - 检查日志是否频繁出现
wait timeout或Connection refused,同时php bin/hyperf.php db:info显示空闲连接数持续趋近于 0
查代码:聚焦高频泄漏点
90% 的泄漏集中在以下几类写法,逐项核对:
-
手动获取连接后忘记 close:比如用
$this->connection->getConnection()拿到原生 PDO,但在 try-finally 中漏掉$pdo = null或未调用$connection->release() -
事务/管道未兜底释放:使用
$redis->pipeline()或$db->transaction()后,若中间抛异常且没写finally块执行exec()或reset(),协程上下文里的连接就“失踪”了 -
闭包持有了连接对象:在定时任务或队列 Job 中,
use ($connection)或use ($container)会延长连接生命周期,尤其当 Job 执行失败重试时,连接被反复复用却不归还 -
长耗时循环中未及时释放中间结果:比如用
Db::select()处理大数据集,即使加了limit,PDO 默认缓冲仍会把整结果集加载进内存,间接拖慢连接回收节奏
改配置:让池子“看得见”泄漏
光修代码不够,得让系统主动报警:
- 在
config/autoload/db.php的 pool 配置里启用泄漏检测:'options' => [ 'leak_detection_threshold' => 5 ](单位秒),表示借用超时即记为泄漏 - 把
max_idle_time从默认 60s 降到 30s,加速闲置连接回收,缩小泄漏窗口 - 将
min_connections设为 1~3,避免启动就占满连接;max_connections按公式估算:QPS × 平均处理时间 × 1.5,例如 QPS=200、耗时 0.2s → 建议设 60~80,而非盲目设 200
验效果:用脚本模拟+监控闭环
修复后别只等线上反馈,本地快速验证:
- 写个压测脚本,连续发起 1000 次 DB 查询,每 100 次查一次
SHOW STATUS LIKE 'Threads_connected',观察数值是否回落 - 在测试环境开启 Hyperf 的连接池统计:配置
'report' => true,启动后访问/metrics看hyperf_db_pool_active_connections和hyperf_db_pool_idle_connections是否稳定波动 - 上线后设置告警:当
Threads_connected / max_connections > 0.8持续 2 分钟,立刻通知


















