ThinkPHP 8 本身不支持数据库连接池,必须通过 think-swoole 扩展在 config/swoole.php 的 database 节点下配置 enable=true 及 min_connections、max_connections 等参数;database.php 中添加 pool 相关字段无效,Db::table() 默认不走连接池,需显式调用 Db::pool()->table() 才生效。

ThinkPHP 8 本身不带数据库连接池,database.php 里加 pool、max_connections 等字段完全无效——配了也白配。
连接池配置入口在 config/swoole.php,不是 database.php
只有启用 think-swoole 扩展、跑在 Swoole 协程环境下,连接池才真正存在。FPM 下无论怎么配都是短连接,Db::table() 每次都新建 PDO。
-
config/swoole.php中的database节点才是唯一有效位置,示例:
'database' => [
'enable' => true,
'min_connections' => 5,
'max_connections' => 50,
'wait_timeout' => 3.0,
'heartbeat' => 30,
],
-
enable必须为true,否则所有参数被忽略 -
min_connections是 Worker 启动时预热连接数,设太低会导致首请求延迟 -
max_connections是单个 Worker 进程内池子总容量(空闲+忙碌),不是全局上限
Db::table() 默认不走连接池,必须显式调用 Db::pool()
这是最常踩的坑:90% 的查询根本没进池,压测时 Too many connections 照样爆。
- ✅ 正确写法:
Db::pool()->table('user')->select() - ❌ 错误写法:
Db::table('user')->select()(绕过池) - ❌ 错误写法:
Db::transaction()(默认非池化,要用Db::pool()->transaction()) - ❌ 错误写法:模型中
self::where()->find()(底层仍走Db::connect())
连接池生效但 QPS 上不去,三处硬限制必须对齐
光配池没用,MySQL、Swoole Worker、协程并发量这三层卡住任何一层,都会让池变成摆设。
立即学习“PHP免费学习笔记(深入)”;
-
MySQL 侧:
show variables like 'max_connections';必须 ≥max_connections×swoole.server.worker_num -
Swoole 侧:
swoole.server.worker_num决定最多几个进程能并发取连接;设成 2,池里有 100 连接也只用得上 2 个 -
协程侧:一个 Worker 启了 200 个协程查库,但池只有 8 个连接,剩下 192 个全在等
wait_timeout
验证是否真复用:同一协程内连续两次调 Db::pool()->getPdo(),打印句柄 ID,相同才说明复用成功。
协程环境下的连接空闲超时与心跳问题
即使进了池,MySQL 默认 wait_timeout=8 秒,闲置连接会被服务端主动断开,下次复用直接抛 SQLSTATE[HY000] [2006] MySQL server has gone away。
- Swoole 配置中加
'heartbeat' => 3,表示每 3 秒发一次 PING - MySQL 侧同步调大:
SET GLOBAL wait_timeout = 300;(需 SUPER 权限) -
database.php中不要设'break_reconnect' => true,协程下它会干扰自动重连逻辑
事务场景更敏感:Db::pool()->transaction() 必须在同一个协程内执行完整流程,否则连接不会归还到池,而是被销毁——看起来像“池失效”,其实是用法错位。



















