swoole4协程mysql连接池需在onworkerstart中为每个worker独立初始化,使用channel管理连接,预热填充、健康检查、try-finally确保get/put成对,避免泄漏与超限。

在 Swoole4 中配置协程 MySQL 连接池,核心是利用协程客户端 + Channel 管理连接生命周期,避免频繁建连、防止连接泄漏、兼顾并发与稳定性。不是简单“new 一堆连接”,而是围绕 Worker 生命周期、连接复用、健康检查三者协同设计。
连接池必须在 onWorkerStart 中初始化
每个 Worker 进程需独立维护自己的连接池,不能跨进程共享,也不能在 onReceive 或协程内重复创建。否则会引发内存暴涨、连接数失控甚至“Too many connections”错误。
- 使用 Swoole\Coroutine\Channel 作为连接队列(官方推荐,比 SplQueue 更可靠,支持超时等待)
- 预热连接:启动时 fill 指定数量(如 10~50),避免首请求冷启动延迟
- 连接配置统一通过数组传入,包含 host、port、user、password、database、charset 等,建议封装为 Config 对象
连接获取与归还必须成对调用
每次数据库操作前 get(),结束后必须 put()。漏掉 put 就等于连接泄漏,池子会逐渐枯竭,后续请求卡在 channel->pop() 超时失败。
- get() 逻辑:channel->pop($timeout),超时返回 false;若为空且未达最大容量,可动态新建连接(但建议预热足量,避免运行时扩容)
- put() 逻辑:归还前执行 $mysql->connected && $mysql->ping(),失效连接直接丢弃(不 put),避免污染池子
- 务必在 try-finally 或 defer 中确保 put() 执行,尤其在异常分支里不能遗漏
连接需主动健康检查与清理
MySQL 可能因 wait_timeout、网络闪断等原因静默断开。仅靠 ping 不够,还需结合时间戳+生命周期管理。
- 每个连接对象附加 last_used_at 时间戳,归还时更新
- 定期(如每 30 秒)在单独协程中扫描池内连接,剔除空闲超 5 分钟或 ping 失败的连接
- 捕获常见错误码:2006(MySQL server has gone away)、2013(lost connection),触发重建
- 事务中的连接禁止归还——需显式标记或用上下文隔离,否则可能破坏事务一致性
参数设置要贴合实际负载
池大小不是越大越好。过小导致排队阻塞,过大浪费内存并压垮 MySQL。
- 参考公式:池大小 ≈ MySQL max_connections × (应用 Worker 数) / (单 Worker 并发请求数),再留 20% 余量
- 典型场景:8 核 CPU、4 个 Worker、MySQL 设置 max_connections=500 → 单 Worker 池建议 100~120
- channel 容量 = 池最大连接数;connect_timeout 建议设为 3~5 秒,query_timeout 控制在 1~3 秒内











