1. 连接池基础概念
1.1 什么是数据库连接池
数据库连接池(Connection Pool)是一种在应用启动时预先创建一定数量的数据库连接,并将其保存在内存池中的技术。当应用程序需要与数据库交互时,不再重复执行 TCP 三次握手、认证鉴权等开销昂贵的建连过程,而是直接从池中“借出”一个可用连接;使用完毕后再“归还”到池中,供其他请求复用。
核心思想:复用连接,避免频繁创建和销毁带来的性能损耗。
1.2 为什么需要连接池
在没有连接池的情况下,每次数据库操作都需要经历完整的建连-使用-断连流程,其代价远超业务逻辑本身。
| 对比维度 | 无连接池(每次新建) | 有连接池(复用) |
|---|---|---|
| TCP 建连 | 每次 1 次三次握手 | 仅首次建连 |
| 认证鉴权 | 每次发送认证包 | 仅首次认证 |
| 内存分配 | 每次分配连接对象 | 池中复用对象 |
| 高并发支撑 | 连接数不可控,易耗尽 | 连接数受池大小控制 |
| 响应延迟 | 高(含建连时间) | 低(直接取用) |
生产环境经验:一次完整的 MySQL TCP 建连 + 认证耗时约 5~15ms。对于 QPS 为 10,000 的服务,若每次请求都新建连接,仅建连开销就占 50~150 秒/秒的 CPU 时间,这是不可接受的。
1.3 连接池的核心参数
Go 标准库 database/sql 通过 sql.DB 对象管理连接池,提供三个核心参数控制池的行为。
1.3.1 最大连接数(MaxOpenConns)
池中允许打开的最大连接总数,包括空闲连接和活跃连接。当所有连接都被占用时,新的请求会进入等待队列,直到有连接归还或超时。
// Go 示例:设置最大连接数
db, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatal(err)
}
db.SetMaxOpenConns(100) // 最大 100 个连接
避坑指南:MaxOpenConns 设置过大(如 1000+)会导致数据库端连接数暴涨,引发 MySQL "Too many connections" 错误;设置过小(如 5)则在高并发下大量请求排队,增加延迟。建议根据数据库规格和业务峰值合理估算。
1.3.2 最小空闲数(MaxIdleConns)
池中保持的最小空闲连接数量。空闲连接预先建好,随时准备被借出,避免突发流量时临时建连的延迟。
db.SetMaxIdleConns(25) // 保持至少 25 个空闲连接
| 场景 | 建议值 | 说明 |
|---|---|---|
| 低流量服务 | 2 ~ 5 | 减少空闲连接占用 |
| 中等流量服务 | 10 ~ 25 | 平衡资源与响应速度 |
| 高并发服务 | 50 ~ 100 | 确保突发流量不建连 |
| Serverless / 短生命周期 | 0 | 避免空闲连接浪费 |
1.3.3 超时时间(ConnMaxLifetime / ConnMaxIdleTime)
连接池需要处理连接老化问题。数据库服务器、防火墙或中间件可能会主动断开长时间未活动的连接,导致池中的连接变为“僵尸连接”。
- ConnMaxLifetime:连接的最大存活时间。超过此时间的连接会被关闭并重建,防止连接泄漏或状态不一致。
- ConnMaxIdleTime:连接在空闲状态下的最大保留时间。超过此时间的空闲连接会被回收,释放数据库端资源。
// 设置连接最大存活时间为 30 分钟
db.SetConnMaxLifetime(30 * time.Minute)
// 设置空闲连接最大保留时间为 5 分钟
db.SetConnMaxIdleTime(5 * time.Minute)
推荐实践:ConnMaxLifetime 通常设置为数据库或中间件连接超时时间的 80%(例如 MySQL wait_timeout=28800s,则设为 23000s)。ConnMaxIdleTime 建议设为 1~5 分钟,避免空闲连接长期占用数据库资源。
1.4 参数配置速查表
| 参数 | Go 方法 | 默认值 | 作用 | 典型值 |
|---|---|---|---|---|
| MaxOpenConns | SetMaxOpenConns(n) |
0(无限制) | 限制最大连接总数 | 50 ~ 200 |
| MaxIdleConns | SetMaxIdleConns(n) |
2 | 保持最小空闲连接数 | 10 ~ 50 |
| ConnMaxLifetime | SetConnMaxLifetime(d) |
0(永不超时) | 连接最大存活时间 | 30m ~ 6h |
| ConnMaxIdleTime | SetConnMaxIdleTime(d) |
0(永不超时) | 空闲连接最大保留时间 | 1m ~ 10m |
Go 版本注意:
SetConnMaxIdleTime 从 Go 1.15 开始支持。若使用更早版本,请升级或自行实现空闲连接回收逻辑。