thinkphp无内置连接池,连接泄漏主因是连接长期占用未释放;需查mysql sleep连接确认,修复要配置pdo参数、修正docker主机名、cli/swoole中显式关闭,并可扩展监控借用时长。

ThinkPHP本身不内置连接池,所谓“连接泄漏”本质是连接被长期占用未释放——常见于事务未提交、对象生命周期异常延长、CLI/Swoole长进程未手动关闭,或配置错导致复用失效。排查要从数据库端看Sleep连接,修复需分层切断源头。
一、快速确认是否真泄漏:查MySQL Sleep连接
登录数据库执行:
SELECT id, user, host, db, time, info FROM information_schema.processlist WHERE command = 'Sleep' AND time > 30;
重点关注 time 字段:若大量连接空闲超30秒(远超PHP请求周期),基本可判定泄漏;若只有几条且 time
同时对比:
- SHOW STATUS LIKE 'Threads_connected'; —— 当前活跃连接数
- SHOW VARIABLES LIKE 'max_connections'; —— 数据库上限
若前者持续接近后者(如145/150),就是真耗尽;若仅30却频繁报1040错误,更可能是“MySQL server has gone away”,属于假性卡死。
二、定位泄漏代码的三类高危场景
泄漏不来自框架,而来自你写的逻辑。重点检查以下位置:
-
事务未配对:中间件、命令行脚本、异步任务中调用了
Db::startTrans(),但没走commit()或rollback(),连接会被锁住直到进程结束 -
静态变量持有Db实例:比如
class OrderService { protected static $db; },让Connection对象生命周期脱离请求范围 - Swoole/Workerman中复用Request生命周期外的Db对象:协程或常驻进程中,直接把TP默认Db实例赋给全局变量或闭包,后续请求会复用已失效连接
三、配置与代码双层修复方案
光改代码不够,配置错会让修复失效。必须同步调整:
-
数据库配置加三项硬性参数:
'deploy' => 1(整数1,非true)、PDO::ATTR_TIMEOUT => 5、PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"——缺一不可,否则复用不生效或建连卡死 -
Docker环境必改hostname:不能写
localhost或127.0.0.1,必须填数据库容器名(如'hostname' => 'mysql'),否则PDO在容器内连的是自己 -
CLI/Swoole场景强制close:命令行脚本末尾加
Db::close();Swoole onRequest回调结束前也建议显式调用,避免连接跨请求残留
四、主动监控超时借用(可选但推荐)
TP无原生告警,但可用轻量扩展实现连接借用时长追踪:
新建app/common/monitor/TrackedConnection.php,继承\think\db\Connection,重写getConnection()打时间戳、close()校验时长并记录日志(如超10秒触发warning)。再在config/database.php中指定'type' => \app\common\monitor\TrackedConnection::class即可生效。
注意:CLI任务可适当放宽阈值(如30秒),避免误报。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











