单机数据库连接超时本质是连接池与服务端生命周期未对齐,需协同配置三组参数:服务端限制(如mysql wait_timeout)、连接池空闲策略(max_idle_time与heartbeat须满足严格时间差)、客户端等待行为(wait_timeout推荐3.0~5.0,connect_timeout建议5.0);同时优先排查连接泄漏。

单机数据库连接超时,本质是连接池与数据库服务端的生命周期没对齐,不是调大某个参数就能解决。关键在三组参数的协同:服务端限制(MySQL wait_timeout 或 PostgreSQL max_connections)、连接池空闲策略(max_idle_time 和 heartbeat)、客户端等待行为(wait_timeout 和 connect_timeout)。配错任意一组,都可能表现为“超时”,但根因完全不同。
先确认数据库服务端真实限制
别依赖文档或默认值,必须查线上实例:
- MySQL 执行:
SHOW VARIABLES LIKE 'wait_timeout';(常见 300~600 秒) - PostgreSQL 执行:
SHOW max_connections;(阿里云 PolarDB 默认 500,KES 常为 100) - 再查当前连接压力:
SELECT count(*) FROM pg_stat_activity;(PG)或SHOW STATUS LIKE 'Threads_connected';(MySQL),若接近上限的 90%,说明服务端已瓶颈
连接池空闲策略必须严守“时间差”逻辑
max_idle_time 不是随便设的数字,它要卡在数据库断连前“提前退场”:
-
max_idle_time必须严格小于服务端wait_timeout,建议设为wait_timeout - 30 -
heartbeat是后台探测间隔,不是开关——它必须 ≤max_idle_time,推荐设为max_idle_time / 2 - 例如 MySQL
wait_timeout = 300,则配max_idle_time = 270、heartbeat = 135 -
min_connections ≥ 2,避免冷启时全重建连接,拖慢首请求
客户端等待参数要兼顾失败速度与资源缓冲
wait_timeout 决定协程排队多久就放弃,不是越小越好,也不是越大越好:
- 设
(如 0.5):瞬时抖动就满屏 <code>WaitTimeoutException,掩盖真实问题 - 设
> 8.0(如 15.0):请求长时间挂起,压住协程资源,反而降低吞吐 - 生产推荐
3.0~5.0,既能容忍短时连接释放延迟,又可快速暴露池子不够、泄漏或慢查询等真问题 -
connect_timeout建议从默认 10.0 降到5.0,减少网络抖动下的无效阻塞
排查连接泄漏比调参更优先
很多“超时”其实是假象——连接被卡住没归还,新请求根本拿不到连接:
- 检查 Redis/MySQL 的
pipeline()或multi()是否漏了exec(),尤其异常路径下没加finally释放 - 用
ss -s | grep ESTAB看服务器实际 ESTABLISHED 连接数,是否长期贴近pool.max_connections - 对异步队列、WebSocket、定时任务等长生命周期协程,单独配连接池,避免和 HTTP 请求争抢











