pdo::attr_persistent => true 仅在 php-fpm 或 apache 模块等常驻进程模式下有效,cli/cgi/swoole 非协程模式无效;需连接参数完全一致才能复用,且存在事务残留、连接数耗尽等风险,非银弹方案。

PHP-FPM环境下才可能复用PDO持久连接
PDO::ATTR_PERSISTENT => true 只有在 PHP-FPM 或 Apache 模块模式下才真正起作用。因为这两种运行模式中,worker 进程会常驻内存,连接才能被缓存下来。如果你用的是 CGI、CLI(比如 cron 脚本)或 Swoole 的非协程 HTTP 服务(未启用连接池),这个选项完全无效——每次请求都会新建连接,脚本结束就销毁,跟普通连接没区别。
验证方式很简单:在脚本里执行 echo php_sapi_name();。输出 fpm-fcgi 或 apache2handler 才算符合条件;cli 或 cgi-fcgi 就别白费劲了。
连接参数必须完全一致才能命中已有持久连接
PDO 不会智能合并“相似”的连接配置。只要 host、port、dbname、username、password 中任意一项不同,就会新建一个连接池,而不是复用。常见踩坑点包括:
- 用
localhost和127.0.0.1被视为两个不同 host - DSN 中漏写
port=3306,而 MySQL 实际监听非默认端口,会导致连接失败或误连到其他实例 - 不同环境(dev/staging/prod)共用同一份代码但数据库账号不同,每个账号各自维持一套连接,无法共享
- 连接字符串里混用
charset=utf8和charset=utf8mb4,也会被视为不同连接
高并发短请求场景下容易撑爆 MySQL 连接数
每个 PHP-FPM worker 进程最多持有一个持久连接,但连接不会自动释放。如果 FPM 配置了 100 个 max_children,MySQL 就可能被占满 100 个空闲连接。而 MySQL 默认 max_connections 通常只有 151,很容易触发 Too many connections 错误。
这时你得同步调整:
- MySQL 端:适当调高
max_connections,但更关键的是检查wait_timeout和interactive_timeout(建议设为 60~120 秒),让闲置连接能及时回收 - PHP 端:FPM 的
pm.max_children不宜盲目拉高,应结合平均并发请求量和单次响应时间估算合理值 - 监控手段:定期查
SHOW PROCESSLIST,观察大量Sleep状态连接是否集中在特定用户或 DB 上
不是所有操作都适合走持久连接
持久连接本质是连接复用,但它不解决事务隔离、连接状态残留等问题。以下情况要格外小心:
- 执行过
SET SESSION sql_mode = 'STRICT_TRANS_TABLES'之类会话级设置后,下次复用该连接时这些设置依然生效,可能影响后续查询语义 - 未显式
ROLLBACK就异常退出的事务,可能让连接卡在IN TRANSACTION 状态,导致下个请求被锁住 - 连接中存在未 fetch 完的 result set(比如只取前几行就丢弃
PDOStatement),某些 MySQL 版本会阻塞后续 query - 如果你的应用依赖连接初始化逻辑(如
SET NAMES utf8mb4),务必确保每次复用前都重置,或改用 DSN 中直接声明charset=utf8mb4
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











