连接池配置关键在“够用、干净、可退”:setmaxopenconns设为数据库max_connections的60%~80%,setmaxidleconns设为1/2~1/3且必须与setconnmaxidletime(推荐3~5分钟)协同调整;事务内严禁混用db.query与tx.query,所有操作须走tx对象并配context超时、defer rollback/commit;rows.close()不可遗漏;db.stats()才是健康核心指标,需持续监控waitcount、inuse、maxidleclosed等字段。

连接池不是调大数字就能扛住海量请求,关键在“够用、干净、可退”——设太高压垮数据库,设太低卡死自己,不配对调 idle 和 lifetime 会满屏 read: connection reset by peer。
SetMaxOpenConns 怎么设才不翻车
它不是 QPS × 耗时的理论值,而是数据库能兜住的硬上限和你并发需求之间的平衡点。
- 先查数据库真实上限:
SHOW VARIABLES LIKE 'max_connections'(MySQL)或SELECT setting FROM pg_settings WHERE name = 'max_connections'(PostgreSQL) - 设为该值的 60%~80%,比如 MySQL 默认 151,就设
db.SetMaxOpenConns(100) - 别信“100 QPS × 20ms = 2 连接”这种算法——线上必须加安全系数,起步至少 10~20
- 观察
db.Stats().OpenConnections:长期 ≥ 90% 上限 → 加;长期 ≤ 30% → 减
SetMaxIdleConns 和 SetConnMaxIdleTime 必须一起动
单设 SetMaxIdleConns 不设 SetConnMaxIdleTime,空闲连接就永远睡着;反过来只设后者,刚建好的连接可能被误杀。
-
SetMaxIdleConns建议设为SetMaxOpenConns的 1/2~1/3(如 Open=100 → Idle=30) -
SetConnMaxIdleTime设5 * time.Minute,防 NAT、SLB、防火墙静默踢掉连接 - 云数据库(如 AWS RDS、阿里云 PolarDB)建议再缩短一点,
3 * time.Minute更稳 - 如果
db.Stats().MaxIdleClosed持续上涨,说明回收太激进,该调高 Idle 或延长 IdleTime
事务里混用 db.Query 和 tx.Query 会悄悄拖垮连接池
事务内调 db.Query 会从全局池另取连接,既不参与事务,又额外占坑——事务卡住时,这个连接就永远挂在那里。
- 所有 SQL 操作必须统一走
tx对象:tx.Query、tx.Exec - 开启事务必须带 context 超时:
db.BeginTx(ctx, &sql.TxOptions{}),其中ctx设 5s 超时 - 务必写
defer tx.Rollback()和tx.Commit(),漏掉一个就锁死连接 - 查完结果集后立刻
rows.Close(),否则连接不会归还
db.Ping() 只是敲门,db.Stats() 才是体检报告
db.Ping() 成功不代表连接池健康,它只验证当前能否连通;真正要盯的是 db.Stats() 返回的实时状态。
-
WaitCount持续上升 → 连接不够用,或 SQL 执行太慢拖住连接 -
InUse == MaxOpenConns且长期不回落 → 连接没归还,查rows.Close()是否漏写、事务是否未 commit/rollback -
MaxOpenConns设了但OpenConnections始终很低 → 可能是 DNS 解析慢、TLS 握手卡住,或上游服务响应延迟过高 - 生产环境必须定期采
db.Stats(),靠日志里一句 “DB initialized” 就上线,等于闭眼开车
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











