hyperf 3.1.67 未新增“连接池刷新”或“json查询”模块,二者实为 v3.1.66 已实现的底层改进:pool::refresh() 触发全量重建而非热重启,json_contains 等需手写原生语句,orm 不支持自动推导。

Hyperf 3.1.67 没有新增“连接池刷新”或“JSON 查询”作为独立功能模块——这两个关键词实际指向 v3.1.66 已落地的两个底层改进:Pool 连接池全量刷新机制、数据库 JSON 字段的 json_contains 等原生查询支持。v3.1.67 是小版本迭代,主要修复兼容性问题,不引入新特性。
为什么 Pool::refresh() 不是热重启,而是全量重建
所谓“连接池刷新”,本质是调用 Pool::refresh() 后,旧连接被标记为不可复用,新协程将从全新初始化的连接池中获取连接。它不是优雅替换单个连接,而是整个池实例被销毁重建:
- 触发时机通常是配置变更(如
max_connections调整)或健康检查连续失败后主动触发 - 旧连接不会立即关闭,但不再参与新请求分发;已借出的连接会在
release()时直接 close,不归还池中 - 重建过程会阻塞新连接请求,直到新池 ready,因此不适合高频调用(比如每秒一次)
-
refresh()不保证事务一致性——正在执行的 SQL 不受影响,但新连接无法继承旧连接的事务上下文
json_contains 查询为何必须用原生语句,不能靠 ORM 自动推导
Hyperf 的 Model 层对 JSON 字段的支持仍停留在读取后 PHP 解析阶段,json_contains 这类 MySQL 原生函数无法通过 whereJsonContains() 这样的链式方法生成,必须手写原生条件:
- ORM 的
where()会把数组参数转成=或IN,而json_contains需要完整函数表达式:JSON_CONTAINS(field, '"value"') - 即使你用
Db::raw('JSON_CONTAINS(...)'),也得确保字段名被正确包裹反引号,否则 MySQL 报错Unknown column 'field' in 'where clause' - JSON 字段索引失效风险高:如果没在 JSON 字段上建虚拟列 + 普通索引(如
ALTER TABLE t ADD COLUMN j_name VARCHAR(255) AS (json_extract(data, "$.name")) STORED),json_contains会全表扫描 - Hyperf 3.1.66+ 支持
->whereRaw('JSON_CONTAINS(?, ?)', [$field, json_encode($value)]),但注意第二个参数必须是 JSON 字符串字面量,不能传 PHP 数组
连接池 max_connections 设太高反而拖慢查询响应
很多人以为把 max_connections 从默认 10 改成 100 就能撑更高并发,结果发现 QPS 不升反降,甚至出现大量 WaitTimeoutException:
- MySQL 服务端有最大连接数限制(
max_connections全局变量),应用侧设再高也没用,还会导致连接等待队列过长 - 每个连接占用内存(约 256KB–1MB),100 个空闲连接就吃掉上百 MB,挤占协程栈和业务内存
- 连接池过大时,
get()查找可用连接的开销上升(内部用 SplQueue + 遍历判断状态),尤其在高并发下竞争更明显 - 真实推荐值 = (预估峰值 QPS × 平均 SQL 耗时)× 安全系数 2–3;例如 200 QPS × 0.08s = 16 → 设为 40 更稳妥,而非盲目拉到 100
真正关键的是连接生命周期管理:max_idle_time 设太长会让无效连接长期滞留,设太短又频繁重建连接。线上建议统一设为 30.0,配合 heartbeat => 30 做主动探活,比依赖超时被动回收更可控。











