Apollo 技术文档Apollo 技术文档
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
  • MMORPG 架构 QA

Q34: 数据库连接池如何设计?

核心结论

连接池的目标不是“多开一些连接”,而是稳定控制数据库访问成本。

一个好用的连接池,至少要解决:

  • 连接创建和复用
  • 上限控制
  • 空闲回收
  • 健康检查
  • 超时与泄漏治理

真正的问题通常不在于怎么写一个池,而在于如何避免业务把数据库当成无限资源。

一、为什么需要连接池

数据库连接建立成本不低,包括:

  • TCP 建连
  • 数据库认证握手
  • 会话初始化

如果每次查询都临时建连接,延迟和资源开销都很高。

连接池的价值主要有两点:

  • 复用已建立连接
  • 控制并发访问数据库的上限

后者往往比前者更重要,因为池本质上还是一个限流器。

二、连接池真正要控制什么

1. 最大并发连接数

池不能只看应用侧需求,还要看数据库实际承受能力。

如果应用无限借连接,数据库会被直接压垮。

2. 等待策略

当池满时,需要明确:

  • 阻塞等待
  • 快速失败
  • 限时等待

不同业务链路适合的策略不同。在线游戏里,主链路通常更适合短等待或快速失败,而不是无限排队。

3. 连接生命周期

连接不是永久有效的,需要处理:

  • 空闲超时
  • 半开连接
  • 数据库重启后的失效连接
  • 长时间不用的老连接

三、池参数不是越大越好

很多系统出问题时,第一个反应是“把池调大”。这往往只是延后故障。

连接池过大常见问题包括:

  • 数据库并发争用更严重
  • 慢查询被放大
  • 业务线程堆积更多请求

所以池大小应基于:

  • 数据库 CPU 和并发能力
  • 查询类型
  • 平均耗时
  • 高峰流量模型

四、健康检查为什么重要

连接池不能假设池里的连接永远可用。

常见做法包括:

  • 借出前做轻量校验
  • 后台定期探活
  • 出现错误时标记失效并重建

如果这层没有,业务会频繁拿到坏连接,导致错误扩散到上层。

五、连接泄漏是最常见的实际问题之一

连接池稳定性很大程度取决于是否能发现连接借出后未归还。

常见治理手段:

  • RAII 或作用域托管
  • 借出超时告警
  • 长时间占用日志
  • 连接使用链路追踪

没有泄漏检测,池再大也会被慢慢耗空。

六、线程模型和连接池要匹配

不要把所有线程都设计成“随时可抢数据库连接”。

更稳妥的做法通常是:

  • 异步任务或数据库工作线程集中访问
  • 主逻辑线程避免长时间阻塞在 SQL 上
  • 重查询和轻查询分池或分通道

这样更容易控制尾延迟。

七、工程上更实用的设计

一个常见的稳妥组合是:

  • 预热少量基础连接
  • 设定明确上限
  • 借连接带超时
  • 借出和归还全链路监控
  • 失效连接自动剔除
  • 空闲连接按需回收

如果查询负载差异很大,还可以进一步拆:

  • 主写连接池
  • 只读连接池
  • 后台任务连接池

八、常见误区

1. 池越大吞吐越高

不对。数据库本身有并发上限,超过后只会加剧争用。

2. 有连接池就不会有数据库瓶颈

不对。池只能复用和限流,不能掩盖慢 SQL 或错误的访问模式。

3. 连接借到就一直持有更省事

这会降低池复用效率,也更容易制造资源饥饿。

参考资料

  • 常见数据库连接池设计与高并发访问治理实践资料
在 GitHub 上编辑此页
最后更新: 3/20/26, 6:06 AM
贡献者: cuihairu