MaxOpenConns应根据数据库max_connections和服务实例数合理分摊,避免过高导致too many connections或过低限制QPS;需监控db.Stats()中WaitCount和WaitDuration,非零即表明连接池成瓶颈。
MaxOpenConns 设多少才不拖垮数据库
设太高,数据库直接报
;设太低,应用排队等连接,QPS 上不去。关键不是“推荐值”,而是看数据库的 max_connections 和你的服务并发模型。
先查数据库侧上限:PostgreSQL 用
,MySQL 用
,别盲目设到 1000+
按服务实例数分摊:比如 DB 允许 300 连接,部署 3 个 Go 服务实例,每个
别超过 80–100(留余量给其他客户端)
上线后盯
或
,如果长期接近上限,说明不是调大,而是得查有没有连接没释放(比如 defer db.Close() 写错位置、或忘了用
而用了
却没
)
MaxIdleConns 和 MaxIdleConnsPerHost 的区别与误用
是整个
实例的空闲连接总数上限;
是 net/http 的字段,和数据库池无关——这是最常见的混淆点,Go 的
根本不认后者。
建议设成和
相同或略低(比如 90%),避免空闲连接占着坑却不干活
如果设为 0,每次查询都新建连接再关,性能灾难;如果设得比
大,实际无效,
会自动截断
注意:空闲连接超时由
控制,不是靠 GC 或连接池自动清理,不设就一直挂着(尤其在低流量时段)
连接泄漏的典型现象和快速定位法
表现不是报错,而是
(或对应 DB 端口)持续上涨,且
里大量状态为
的连接,时间戳几小时没变。
最常见原因:用
后没调
;
不需要 Close,但
必须
检查所有
是否写在
分支外——写在里面等于根本没执行
临时加监控:在
后立刻打日志,再定期 log.Printf("open: %d, idle: %d", db.Stats().OpenConnections, db.Stats().Idle)
高并发短连接场景下要不要调小 ConnMaxLifetime
要,但不是为了“让连接更健康”,而是防止连接池在数据库主从切换、连接被中间件(如 pgbouncer)踢掉后,还拿着已失效的连接继续发请求,结果卡住几秒才超时。
立即学习
“
go语言免费学习笔记(深入)
”;
设 5–15 分钟足够,太长(如 1 小时)会让失效连接滞留太久;太短(如 30 秒)则频繁新建销毁,增加握手开销
它和
配合用效果最好:前者防“老而病”,后者防“闲而占”
注意:这个值是连接从创建起的总存活时间,不是空闲时间,别和
搞混
真正难的不是算数字,是上线后盯着
里的
和
——只要这两个非零,说明连接池已经成了瓶颈,参数就得动。
too many connectionsSHOW max_connectionsSHOW VARIABLES LIKE 'max_connections'MaxOpenConnspg_stat_activitySHOW PROCESSLISTdb.QueryRowdb.Queryrows.Close()MaxIdleConns*sql.DBMaxIdleConnsPerHostdatabase/sqlMaxIdleConnsMaxOpenConnsMaxOpenConnssql.DBSetConnMaxIdleTimenetstat -an | grep :5432 | wc -lpg_stat_activityidledb.Queryrows.Close()db.QueryRowQuerydefer rows.Close()if err != nildb.SetMaxOpenConnsConnMaxLifetimeSetConnMaxIdleTimeMaxIdleConnsdb.Stats()WaitCountWaitDuration