连接池是预创建并复用的长连接集合,依赖长连接存活但具备调度、健康检测等管理能力;单开pdo持久化不等于连接池,协程中未归还会导致泄漏,需try/finally保障put()执行。

连接池不是长连接,但依赖长连接存活
连接池本身不等于长连接,它是一组被预先创建、复用并受控管理的长连接集合。每个池内连接在建立后保持打开状态(即“长连接”),但连接池额外承担了调度、健康检测、超时控制、归还校验等职责。如果只开启 PDO 的 PDO::ATTR_PERSISTENT 或 MySQLi 的 MYSQLI_CLIENT_FOUND_ROWS,那只是单个连接的“长连接化”,没有池化调度能力——协程并发时仍可能抢到同一个连接,导致阻塞或状态污染。
协程环境下不手动归还会直接泄漏连接
在 Swoole 协程中使用 MySQLPool 或自定义 Channel 池时,$pool->get() 或 $pool->pop() 拿到的是一个已建立的连接对象;但若业务逻辑抛异常、提前 return、或忘记调用 $pool->put($conn) / $pool->push($conn),该连接就永远滞留在协程栈里,不再回到池中。后果是:池迅速耗尽,后续请求卡在 get() 超时,错误日志出现 "Connection pool is empty" 或 "timeout while pop from channel"。
- 必须用
try/finally包裹关键路径,确保put()执行 - 不要在事务未结束前归还连接,否则上下文丢失,
commit()会失败 - 若连接执行出错(如
mysqli_errno() !== 0),应put(null)而非原连接,触发池自动重建
连接池大小 ≠ 并发数,需按压测结果反推
设连接池大小为 20,不代表能稳定支撑 20 QPS 或 20 并发请求。真实吞吐取决于 SQL 执行耗时、网络延迟、协程调度开销。例如平均查询耗时 100ms,理论最大吞吐 ≈ 20 ÷ 0.1 = 200 QPS;但若某条慢查拖住连接 2s,该连接 2 秒内无法复用,池实际可用连接数瞬时跌至 19,高并发下极易排队。所以:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 初始配置建议从 10–20 开始,用
ab或wrk压测,观察mysqladmin proc中活跃连接数与响应 P95 延迟拐点 - 避免盲目设大(如 100+):MySQL 默认
max_connections通常为 151,客户端池过大反而挤占服务端资源 - 空闲连接不会自动释放,除非你实现心跳检测 +
Channel超时淘汰逻辑
长连接失效时连接池未必能自动恢复
Swoole 的 MySQLPool 有基础健康检测(如 ping()),但仅在 get() 时触发。若连接因网络闪断、MySQL 主动 kill、防火墙超时(如 AWS NLB 默认 350s)而静默失效,而业务代码又没做 try/catch 捕获 mysqli_connect_error() 类异常,该连接会被错误地 put() 回池,下次取出直接报错 "MySQL server has gone away"。
真正可靠的方案是:在 get() 后、执行前加一次轻量 $conn->query("SELECT 1") 验证,或启用 MySQLPool 的 options['check_interval'] 参数(需 Swoole ≥ 5.0.3),让后台协程定期探活。否则,别迷信“自动重连”——它只对刚建立就失败的连接有效,对运行中掉线的连接无感。










