关键不在“多库”本身,而在于每个连接池的独立健康策略必须精准匹配对应数据库的服务端参数:需逐个确认mysql的wait_timeout、postgresql的tcp_keepalives_idle、redis的max_idle_time,并为每个库单独配置max_idle_time(严格小于服务端值-30)和heartbeat(≤max_idle_time/2),同时分清pool.wait_timeout(排队超时,推荐3.0~5.0秒)、connect_timeout(建连超时,建议5.0秒)及pdo执行超时。

Hyperf 多数据库连接超时断开重连,关键不在“多库”本身,而在于每个连接池的独立健康策略必须精准匹配对应数据库的服务端参数。配置错一个池,就可能让整个业务链路卡在某个库上。
先查清各数据库的真实 wait_timeout
不同数据库、甚至同类型不同实例(如主从、云厂商 RDS),wait_timeout 值往往不同,不能统一设。必须逐个确认:
- MySQL:执行
SHOW VARIABLES LIKE 'wait_timeout';,常见值为 60、300、600 秒 - PostgreSQL:没有 wait_timeout,对应的是
tcp_keepalives_idle(单位秒),查法:SHOW tcp_keepalives_idle; - Redis:服务端无类似参数,但客户端需配合
max_idle_time防止连接空闲失效
每个连接池单独配 max_idle_time 和 heartbeat
连接池不是共享心跳,而是按库隔离。必须为 default、log_db、report_db 等每个连接单独设置:
-
max_idle_time 必须严格小于对应 DB 的
wait_timeout(建议减 30 秒) -
heartbeat 推荐设为
max_idle_time / 2,且不能大于它 - 例如 MySQL 实例
wait_timeout = 300→ 设max_idle_time = 270、heartbeat = 135 - PostgreSQL 若
tcp_keepalives_idle = 600,则max_idle_time建议 ≤ 570,heartbeat≤ 285
wait_timeout 和 connect_timeout 要分清用途
这两个“超时”常被混淆,但作用完全不同:
-
pool.wait_timeout:协程在池里排队等空闲连接的最长容忍时间,推荐 3.0~5.0 秒。太小易报
WaitTimeoutException,太大掩盖连接不足问题 - pool.connect_timeout:建立新 TCP 连接的超时,线上网络抖动时建议从默认 10.0 降到 5.0,避免阻塞协程
- PDO 层 timeout(options.ATTR_TIMEOUT):SQL 执行级超时,建议设为 3 秒,防慢查询拖垮整个协程
断线重连生效的前提是连接能归还
90% 的“重连不生效”,其实是连接泄漏导致新协程根本拿不到连接去触发重连逻辑:
- 检查所有
$db->transaction()、$redis->pipeline()是否都有finally或安全封装(如withPipeline()) - 定时任务、WebSocket 长连接里的 DB/Redis 操作最容易漏释放,务必加日志验证
Context::has($key)是否为 true 且未清理 - 多库切换时,确保
Db::connection('xxx')获取的实例生命周期受控,不要长期持有静态引用











