pdo::attr_persistent 不是连接池,仅复用连接;php 8.5.5 无原生连接池,需依赖 swoole 协程池、proxysql 或 doctrine(仅限低并发 cli)等外部方案。

PDO::ATTR_PERSISTENT 不是连接池,只是复用连接;PHP 8.5.5 本身仍无原生连接池支持,必须靠外部机制或运行时环境补足。
为什么 PDO::ATTR_PERSISTENT 不能当连接池用
开启 PDO::ATTR_PERSISTENT => true 后,连接在 PHP-FPM 进程生命周期内保持打开,下个请求可能复用——但这依赖进程复用,不是可控的池管理:
- 连接数 = PHP-FPM 子进程数 × 每进程最多持有一个同 DSN 的持久连接,无法按需扩容缩容
- 事务未提交、临时表未清理、会话变量残留,会导致后续请求出错
- MySQL 的
wait_timeout与 PHP 进程空闲时间不一致,容易出现 “MySQL server has gone away” 错误 - 没有连接健康检查、超时归还、最大空闲数控制等池核心能力
Swoole 协程环境下用 Swoole\ConnectionPool 管理连接
这是目前 PHP 8.5.5 下最接近“真连接池”的方案,前提是应用已迁移到 Swoole 常驻进程模型(如 HTTP Server 或 Task Worker):
- 连接池对象在 Worker 启动时初始化,每个 Worker 维护独立池,避免跨进程竞争
- 创建池时指定回调函数,例如
function() { return new Co\MySQL(); },注意需提前调用connect()并检查返回值 - 使用
$pool->get()获取连接,$pool->put($conn)归还;务必用try/finally保证归还,否则池会耗尽 - 推荐设置合理容量:例如
new Swoole\ConnectionPool(..., 32),过大会占满 MySQLmax_connections,过小则协程阻塞 - 注意
Co\MySQL不支持预处理语句绑定参数(prepare/execute),如需该功能,得改用co\Redis+ 自研封装或切到ext-mysqlnd+ 协程化 PDO
ProxySQL 是对 PHP 代码零侵入的连接池方案
如果你还在用 PHP-FPM + Apache/Nginx,又想获得连接复用、负载均衡、查询缓存等能力,ProxySQL 是最稳妥的选择:
- PHP 代码完全不用改,只需把数据库 host 改为
127.0.0.1:6033(ProxySQL 默认监听端口) - ProxySQL 自身维护后端 MySQL 连接池,可配置
mysql-pool_idle_time、mysql-pool_max_size等参数 - 它能自动剔除失效节点、重试失败查询、路由读写分离,这些逻辑 PHP 层无需感知
- 监控关键指标:ProxySQL 的
stats_mysql_connection_pool表,重点关注ConnUsed和ConnFree是否长期趋近于max_connections - 注意 ProxySQL 配置变更后需执行
LOAD MYSQL SERVERS TO RUNTIME和SAVE MYSQL SERVERS TO DISK才生效
Doctrine DBAL 的 PoolingConnection 只适合低并发 CLI 场景
虽然 Doctrine 提供了 PoolingConnection 包装器,但它本质是单进程内存池,在 PHP-FPM 中每请求新建一个池实例,毫无复用价值:
- 仅适用于命令行脚本(如定时任务),且并发量极低(≤10 QPS)时才有点意义
- 池中连接未做健康检测,一旦 MySQL 主动断连,后续获取的连接直接抛异常
- 不兼容协程,
getConnection()是同步阻塞调用,会拖垮 Swoole 应用吞吐 - 如果坚持要用,至少配合
ping()和重连逻辑,但不如直接用 Swoole 原生池或 ProxySQL
PDO::ATTR_PERSISTENT 就高枕无忧,结果线上突然大量 Lost connection to MySQL server during query 报错——那往往是因为没清理 SQL_MODE 差异、没重置 AUTOCOMMIT、或者 MySQL 主动踢掉了空闲太久的连接。连接复用不是开个开关就完事,得配套清理、探测、降级三板斧。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











