标准答案
- 使用上下文管理器保证连接、游标和事务在异常路径释放或回滚。
- 观察池大小、借出、空闲、等待时长、超时和连接创建失败。
- 关联慢查询、锁等待、网络、事务长度和请求取消,区分持有连接慢和无法获得连接。
- 池上限服从数据库总连接预算,超限时应排队、拒绝或降级。
题目解析
连接池耗尽时,先区分“没有空闲连接”和“连接本身不可用”。前者通常表现为应用在 acquire 阶段等待,后者可能表现为新连接建立失败、连接被数据库关闭或事务处于异常状态。把池等待时间、借出数量、最长持有时间和数据库活动会话放在同一条时间线上,才能定位是泄漏、慢事务还是容量确实不足。
连接、游标和事务都应有明确的作用域。请求取消、异常和超时必须触发回滚或释放;长事务即使没有泄漏,也会持有锁和连接。池大小不是越大越好,它应服从数据库 CPU、锁、磁盘和最大连接数,超过容量后应排队、拒绝或降级。
排查时还要检查连接是否跨线程或跨事件循环错误复用、数据库代理是否有独立上限,以及重试是否在连接获取超时后形成风暴。修复后应验证流量回落时池占用是否恢复、事务时长是否下降,而不是只看错误率短暂变低。
常见误区
- 误区:只在成功路径关闭连接。改正:使用上下文管理器或 finally 覆盖异常、取消和超时路径,并确保事务回滚。
- 误区:每个请求都新建 engine 或 pool。改正:把池绑定到应用生命周期,启动时创建,停机时关闭。
- 误区:连接获取超时后无限重试。改正:设置总 deadline,限制重试次数,并在资源耗尽时快速失败或降级。