ThinkPHP 6.1“连接池耗尽+接口超时”本质是请求卡在「等连接」环节,需分四层排查:一、确认真耗尽(Threads_connected接近max_connections)或假性卡死(日志含“gone/1040/refused”);二、验证think-orm≥3.0且pool配置在数据库项下、禁用deploy=1;三、检查事务未提交、static变量持有、Swoole协程复用等连接泄露;四、协同设置connect_timeout(DSN中)、get_timeout(pool内毫秒级)、wait_timeout(MySQL端≤max_lifetime)。

ThinkPHP 6.1 出现“连接池耗尽 + 接口超时”,本质是请求卡在「等连接」环节,不是数据库慢,而是连接管理出了问题。得从连接是否真被占满、是否漏还、是否拿不到、是否连不上四个角度分层排查。
一、先确认是不是真耗尽,还是假性卡死
别急着改配置,先看数据库真实负载:
- 进应用容器执行:mysql -h mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"(host 必须填数据库服务名,如 mysql,不能写 127.0.0.1)
- 对比输出值和
max_connections(MySQL 默认 151)。若Threads_connected接近上限(比如 148/150),才是真耗尽;若只有 20–30 却报超时,大概率是建连失败或 DNS 解析卡住 - 查日志:
tail -n 50 runtime/log/*.log | grep -i "gone\|1040\|refused\|timeout"。高频出现 MySQL server has gone away,说明是 wait_timeout 导致连接失效,不是数量不够
二、检查连接池是否真正启用
TP6.1 只有配合 think-orm v3.0+ 才支持连接池,旧版本或配置错都会白配:
- 确认 composer 中
topthink/think-orm版本 ≥ 3.0(运行composer show topthink/think-orm) - 检查
config/database.php中 MySQL 配置块是否含'pool' => ['max_active' => 20],且该配置在具体数据库项下(如'mysql' => [ ... ]内),不在顶层 - 删掉
'deploy' => 1—— 这是 TP5 的长连接方案,在 TP6.1+ 连接池中已废弃,混用反而干扰池行为
三、定位连接“拿不到”还是“还不上”
耗尽常因连接被长期占用却不释放,重点查这些场景:
立即学习“PHP免费学习笔记(深入)”;
-
事务未收尾:中间件、命令行任务、异步回调里调了
Db::startTrans(),但没配对commit()或rollback() -
对象生命周期异常:把
Db实例赋给了static属性、全局变量,或在 Swoole 协程中跨请求复用 -
闭包事务未退出:用了
Db::transaction(function () { ... }),但函数内抛异常未被捕获,导致回滚逻辑跳过 - 数据库端查
SHOW PROCESSLIST,看是否有大量Sleep状态连接,持续时间远超 PHP 请求周期(>30s),基本可锁定泄露点
四、关键超时参数必须协同设置
只调 get_timeout 不解决问题,三个超时要一起控:
-
建连超时:DSN 中加
;connect_timeout=3(如mysql:host=192.168.1.100;port=3306;connect_timeout=3),并把hostname改成 IP,绕过 DNS -
取连接超时:在 pool 配置里设
'get_timeout' => 1000(单位毫秒),避免线程傻等;注意它只在池满时生效,设太高会拖垮整个服务 -
连接保活底线:MySQL 的
wait_timeout建议设为 300(5 分钟),同时确保连接池的max_lifetime小于它(如设 240 秒),防止取出已断连



















