setmaxopenconns应设为数据库max_connections的60%~80%(如mysql默认151则设100~120),setmaxidleconns不超过其30%(通常10~30),并必须配合setconnmaxlifetime(如1小时)防止幽灵连接。

连接池配置不对,数据库响应就卡在排队上,不是代码慢,是连接没排上队。
db.SetMaxOpenConns 和 db.SetMaxIdleConns 怎么设才不翻车
这两个值不是随便填的数字,它们直接决定连接能否及时分配出去。设小了,高并发时请求在等连接;设大了,数据库扛不住,报 Too many connections 错误。
-
SetMaxOpenConns应略小于数据库服务器的max_connections(比如 MySQL 默认 151,这里设 100~120 比较稳妥) -
SetMaxIdleConns不建议超过SetMaxOpenConns的 30%,通常 10~30 即可;设太高反而浪费空闲连接,还可能拖慢连接回收 - 必须配
SetConnMaxLifetime,比如time.Hour,否则长连接可能因网络中断或数据库重启而卡死,变成“幽灵连接”
为什么加了连接池还是超时?检查这三处
常见错误不是没配池,而是配了但被其他逻辑绕过或覆盖:
- 每次 HTTP 请求都调用
sql.Open—— 这会新建一个独立连接池,完全没复用,必须全局复用同一个*sql.DB实例 - 中间件或 handler 里写了
defer db.Close()—— 这会提前关掉整个池,后续请求全失败 - 没设
context.WithTimeout给db.Query或db.Exec,导致单个慢查询拖垮整条连接,池里连接逐渐被占满
MySQL 驱动要不要加 parseTime=true 和 loc=Local
加,但只在真需要 time.Time 类型字段时才开。它们会影响性能和时区行为:
-
parseTime=true让驱动把 DATETIME 字段转成time.Time,但解析开销略增;如果业务只用字符串或 int 时间戳,关掉它能省一点 CPU -
loc=Local避免时区转换错乱,尤其当数据库用UTC而应用部署在东八区时;但若 DB 和服务时区一致,可省略 - DSN 示例:
user:pass@tcp(127.0.0.1:3306)/dbname?parseTime=true&loc=Local
最常被忽略的是连接生命周期管理:不设 SetConnMaxLifetime 或 SetMaxIdleTime(Go 1.15+),连接池里的旧连接不会自动清理,久而久之会出现“能连上但查不出数据”的诡异问题。











