数据库连接池参数怎么定:不是越大越好

米阳 2024-7-13 4 7/13

连接池配小了报「获取连接超时」,配大了数据库 CPU 打满。这两个极端我都遇到过,最后发现参数得按公式算,不能凭感觉。

先理解连接数不是免费的

每个 MySQL 连接在服务端对应一个线程,占内存(默认约 256KB 起,实际更高)和上下文切换开销。1000 个连接不会让数据库快 10 倍,只会让它忙于调度。

PostgreSQL 更明显——它是进程模型,每个连接一个进程,几百个连接就把内存吃光了,所以才有 PgBouncer 这种东西。

经验公式

连接数 = CPU 核数 × 2 + 有效磁盘数

4 核机器,连接数 8~10 就够处理绝大多数业务。这个公式来自 PostgreSQL 社区,对 MySQL 也基本适用,因为它假设的是「连接在等 IO,不是等 CPU」。

反直觉的地方:连接数应该和数据库的核数匹配,不是和应用服务器的数量匹配。10 台应用服务器每台配 20 个连接 = 200 个连接打到一个 4 核数据库,数据库直接崩。

池子参数

以 HikariCP 为例:

maximum-pool-size: 10        # 上限,按上面的公式
minimum-idle: 10             # 与上限一致,避免频繁创建
connection-timeout: 3000     # 拿不到连接等 3 秒就报错,不要等 30 秒
idle-timeout: 600000         # 空闲 10 分钟回收(配合 minimum-idle 一般用不到)
max-lifetime: 1700000        # 比 MySQL 的 wait_timeout 小一点

max-lifetime 要小于数据库的 wait_timeout(默认 8 小时)。否则连接被服务端断掉,池子还以为是好的,取出来用就报「Communications link failure」。这个错我排查过两次,都是这个原因。

慢查询会放大连接占用

连接被占用的时间 = 查询耗时。一条 5 秒的慢查询会把连接占 5 秒,10 个连接 = 每秒只能处理 2 个请求。

所以连接池调优的前提是先优化慢查询。SQL 从 5 秒优化到 50 毫秒,等于连接处理能力提升 100 倍,比加连接数有效得多。

快速连接 vs 事务连接

短事务、快查询,连接数可以少;长事务(比如批量处理)会长时间占用连接,要么单独配一个小池子,要么把批量操作拆小。

怎么监控

# 定期打印池状态
print(f"active={pool.active} idle={pool.idle} waiting={pool.waiting}")
  • waiting 长期 > 0:连接不够,或者有慢查询
  • active 接近上限但 waiting = 0:刚好,不用加
  • idle 一直等于上限:可以调小 minimum-idle 省资源

结论

先优化 SQL,再按核数设连接数,max-lifetime 小于数据库超时,监控 waiting 而不是盲目加参数。做到这四条,连接池问题基本不会再有。

- THE END -

米阳

7月13日09:40

最后修改:2024年7月13日
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论