sql.DB 本身就是一个连接池,但默认参数是为”单机演示”设计的。线上服务不调这三个参数,高并发下大概率会出现”连接打满、请求排队、P99 飙升”。
三个关键参数
SetMaxOpenConns(n):允许同时打开的最大连接数,防止把数据库打挂的保险丝SetMaxIdleConns(n):连接池保留的空闲连接数,决定突发流量的响应速度SetConnMaxLifetime(d):连接最长存活时间,规避数据库端的 max_age 强制断开
一个常见的错误配置
db, _ := sql.Open("mysql", dsn)
// 什么都没设,默认 MaxOpenConns 是无限制的
无限打开连接意味着:流量一涨,MySQL 的 max_connections 先爆,报错 too many connections,整个服务连带数据库一起雪崩。
正确做法是压住上限:
db.SetMaxOpenConns(50) // 单实例建议 20~50,按库规格调整
db.SetMaxIdleConns(10) // 约为 Open 的 1/3~1/5
db.SetConnMaxLifetime(time.Hour) // 小于数据库的 wait_timeout
怎么判断调小了还是调大了
关注这两个指标:
db.Stats().WaitCount—— 等待连接的次数,持续增长说明MaxOpenConns太小db.Stats().MaxIdleConnsClosed—— 因空闲被关闭的连接,数值很高说明MaxIdleConns偏大,白建了连接
压测时把 WaitCount 控制在接近 0,同时数据库 CPU 不超过 60%,就是合理区间。
一个容易忽略的坑
sql.Open 不会真正建立连接,它只是校验参数。如果 DSN 写错,错误要到第一次查询才暴露。建议启动时做一次探活:
if err := db.Ping(); err != nil {
log.Fatalf("数据库连接失败: %v", err)
}
把探活放在健康检查里,比等到用户报障再发现要体面得多。