thinkphp 6 默认不支持 pdo 原生长连接,因 connection 类析构时强制置空 pdo 对象,且 mysql pdo dsn(非 mysqlnd)不识别 persistent 参数;即使启用 'persistent' => true,也会被连接池销毁逻辑绕过,导致连接无法复用。

ThinkPHP 6 默认不支持 PDO 原生长连接,加 'persistent' => true 基本无效——它会被框架的连接池销毁逻辑绕过。
为什么 'persistent' => true 在 TP6 里大概率没用
TP6 的 Connection 类在析构时强制执行 $this->pdo = null,PDO 对象一销毁,底层 socket 就断开,PDO::ATTR_PERSISTENT 根本没机会生效。更关键的是,MySQL 的 PDO DSN(非 mysqlnd)压根不识别 persistent 参数;即使你用的是 mysqlnd,TP6 官方也未维护 mysqli 驱动,'persistent' => true 写在 database.php 里只是被忽略。
常见错误现象包括:show processlist 看不到复用连接、QPS 上去后仍报 Too many connections、CLI 脚本运行超时后复用连接直接失败。
- Apache prefork 模式下,
persistent完全失效(进程不复用) - FPM 模式下仅对同一 worker 进程内有效,但 TP6 连接管理器不保证复用路径
- 框架层的
break_reconnect若未设为true,连接异常后不会自动重连,反而卡死等待
真正起效的是 deploy => 1 + 连接池配置
TP6 提供的务实方案不是“长连接”,而是“连接复用池”。核心开关是 deploy => 1,它会启用读写分离基础结构——哪怕你没配从库,也会激活连接缓存逻辑。
必须配合以下配置才实际生效:
-
'deploy' => 1:必需,否则连接池逻辑不触发 -
'pool_size' => 20:限制最大空闲连接数,防 MySQLmax_connections耗尽 -
'break_reconnect' => true:连接异常时自动重建,避免阻塞
注意:该池只对「同 hostname、同 database、同 username/password」的请求复用;换库名或改账号会新建池,无法共享。
Connection timed out 错误的真实来源
报 SQLSTATE[HY000] [2002] Connection timed out 时,90% 不是网络连不上 MySQL,而是 TP6 连接池在等一个可用连接超时了。根源可能包括:
-
'host'写成域名而非 IP,DNS 解析慢拖垮首次连接 - MySQL 的
wait_timeout设为 60 秒,而队列任务运行超时,连接被服务端主动 kill,下次复用就断 - 事务闭包中发生未捕获异常或提前
return,导致连接未归还池,池逐渐枯竭 - 连接池默认不自动清理空闲连接,长期运行后堆积大量 idle 连接,占满 MySQL 上限
验证方法:直接连 MySQL 执行 SHOW PROCESSLIST,看连接数是否随请求增长却不回收。
高并发下必须同步调优 MySQL 和 PHP-FPM
光改 TP6 配置不够,两个硬瓶颈必须对齐:
- MySQL 端:
max_connections至少设为pool_size × worker 数量 × 1.5,避免服务端拒绝新连接 - PHP-FPM 端:确认
pm.max_children不超过 MySQLmax_connections,否则必然爆Too many connections - Linux 内核:检查
net.core.somaxconn和fs.file-max,防止系统级连接数限制先于 MySQL 触发
最易被忽略的一点:TP6 连接池没有空闲连接自动驱逐机制,pool_time 参数不存在;若业务存在明显波峰波谷,需自行加定时任务清空 idle 连接,或改用 Swoole 自建池。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











