hyperf 3.1.68 的 pool 连接池采用全量刷新机制,即任一连接失效时丢弃全部现存连接并批量重建新连接;该机制需同时满足 heartbeat > 0、test_on_return = true 且失效连接数 ≥ min_connections 才触发,旨在确保连接状态一致,避免单连重建引发的建连风暴与脏连接复用。

Hyperf 3.1.68 中的 Pool 连接池全量刷新机制,不是“自动重连”或“优雅重启”,而是当连接池中任意连接被判定为失效(如网络断开、MySQL server has gone away)时,**整个池子会丢弃所有现存连接,重新批量创建一批新连接**。这解决了旧版本中部分连接失效后仍滞留、导致后续请求随机失败的问题。
为什么需要全量刷新而不是单个连接重建
在高并发长连接场景下,数据库服务端可能静默关闭空闲连接(如 MySQL 的 wait_timeout),而连接池若只对单个失效连接做惰性重建,会导致:
- 多个连接陆续触发重建,引发瞬时建连风暴,加重数据库负担
- 部分连接已失效但未被及时检测,仍在活跃集合中被分配出去,造成
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away - 连接状态不一致(如事务残留、字符集错乱),单个重连无法保证上下文干净
全量刷新强制“清零重来”,确保池内所有连接处于同一健康基线,适合对一致性要求高于吞吐抖动容忍度的生产环境。
Pool 全量刷新的触发条件与配置控制
该机制默认启用,但仅在满足以下全部条件时才会真正执行:
- 连接池配置中启用了心跳(
heartbeat> 0),且心跳探测失败 - 连接归还时校验失败(
test_on_return= true,且验证查询如SELECT 1返回错误) - 当前池中失效连接数 ≥
min_connections(避免低水位时误刷)
关键配置项(位于 config/autoload/db.php 或对应 Pool 配置):
'pool' => [
'min_connections' => 5,
'max_connections' => 20,
'heartbeat' => 30.0, // 必须 > 0 才启用心跳驱动的全量刷新
'test_on_return' => true, // 必须开启,否则无法捕获归还时的连接异常
'max_idle_time' => 60.0, // 配合 heartbeat 控制闲置连接回收节奏
],
注意:heartbeat 设为 -1(禁用心跳)或 0,将完全绕过该机制,退回到旧版单连接重建逻辑。
全量刷新对协程与业务的影响
刷新过程是同步阻塞的 —— 它发生在 Worker 进程内,且会暂停当前连接池的 get() 请求,直到新连接批量建立完成。这意味着:
- 若
max_connections设得过大(如 100),刷新耗时可能达数百毫秒,期间新请求会卡在wait_timeout内等待 - 正在使用中的连接(在
active pool中)不受影响,但它们归还后会被立即丢弃,不会进入新池 - 刷新期间无连接可用时,会抛出
Hyperf\Pool\Exception\ConnectionException: Connection pool exhausted,而非静默降级
因此,上线前务必压测刷新场景:模拟网络闪断后,观察 get() 延迟毛刺是否超出业务 SLA。
如何确认你的连接池已启用全量刷新
最直接的方式是主动触发一次失效:
- 手动 kill 掉数据库一侧的部分连接(
KILL [id]) - 或临时调高 MySQL 的
wait_timeout到 5 秒,等连接闲置超时 - 随后发起一次查询,观察日志是否出现类似:
[INFO] DbPool "default" triggered full refresh: destroyed 5 connections, created 5 new ones
若日志只有单条 Recreated connection due to failure,说明配置未生效或条件未满足 —— 重点检查 heartbeat 和 test_on_return 是否为 true。
全量刷新本质是用可控的“停顿”换确定的“干净”,它不解决连接泄漏,也不替代合理的 min_connections 和 max_idle_time 设置。真正容易被忽略的是:一旦启用,你就不能再依赖“连接复用带来的状态延续性”,比如在连接上缓存用户权限标识 —— 每次刷新后都是全新连接。











