游戏卡顿白皮书 › L12 数据库
连接池耗尽 Connection pool exhaustion
原因 ID db-pool · 主责 研发团队·服务器开发 · 配合 运维团队·数据库运维
在含图示和实验的完整版中打开此卡片 →
与 DB 建立的连接数是固定的,慢查询占住连接后,其余请求只能等待。
起因 慢查询或请求激增,所有连接都在使用中 → 结果 新请求要等到有空闲连接 → 画面表现 登录时无限加载,存盘变慢,超时
- 症状
- 连不上/无限加载, 操作延迟
- 因素
- 停顿, 延迟
- 谁会遇到
- 全服, 仅特定功能
- 何时出现
- 刚登录/维护结束后, 人多的时候
- 负责方
- 主责 研发团队·服务器开发 · 配合 运维团队·数据库运维
- 研发团队要做的事
- 消除慢查询,调整连接池大小和等待超时(不要盲目调大连接池),按功能拆分连接池。
- 运维团队要做的事
- 确认 DB 的最大连接数和 CPU、IOPS 余量;扩容或弹性伸缩前,确认服务器数 × 连接池大小不超过最大连接数;把连接等待、锁等待指标加入监控。
- 数值参考
- 所需连接数可以按“每秒请求数 × 每个请求占用连接的时间”估算。每秒 2,000 个请求、每个 5 ms,平均有 10 个连接一直在忙。考虑到请求集中的时候,通常配置两三倍。查询慢到 150 ms 时,同样的请求量需要 300 个连接。
- 监控图上
- 触顶后走平 · 正在使用的 DB 连接数、连接等待时间
- 查看位置
- 在 DB 侧按游戏服务器统计连接状态。MySQL 看 SHOW PROCESSLIST 的 Host、Command(空闲连接为 Sleep)、Time,以及 Threads_connected、Threads_running 和被拒绝的连接数 Connection_errors_max_connections。PostgreSQL 把 pg_stat_activity 按 client_addr、state 分组统计。游戏服务器的连接池库如果输出等待数、等待时间,也一并查看
- 确认依据
- 某台游戏服务器的连接数达到连接池上限、全部在执行查询,空闲连接为 0,这段时间登录、存盘都在等待。或者 DB 总连接数达到 max_connections,新连接被拒绝
- 排除依据
- 空闲连接充足仍然慢,是查询本身慢或 DB 资源饱和,看“缺少索引的查询”(db-no-index)、“热点行锁竞争”(db-hot-row)
- 确认手段
- 运维工具即可确认(无需游戏代码)
- 深入了解
- 盲目调大连接池,只会增加 DB 的 CPU 消耗和锁竞争,大家一起变慢。另外,服务器数 × 连接池大小超过 DB 最大连接数时,新扩容或重启的服务器连连接都建不起来。这在弹性伸缩或维护结束后很常见。
出处
- Number Of Database Connections PostgreSQL
DB 资源用尽后,再增加连接反而会降低吞吐量;让活跃连接数与资源相匹配、其余请求排队,延迟和吞吐量都更好 - Too many connections MySQL
max_connections 用完后,新连接会因 Too many connections 错误被拒绝 - Connections and Authentication (PostgreSQL Documentation) PostgreSQL
max_connections:并发连接数上限,默认通常为 100 - SHOW PROCESSLIST Statement MySQL
Host(客户端地址),Command(空闲会话为 Sleep),Time,State - Server Status Variables MySQL
Threads_connected、Threads_running,Connection_errors_max_connections(因达到 max_connections 而被拒绝的连接数) - The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
pg_stat_activity:每个连接的 client_addr 和 state(active、idle、idle in transaction 等)
相关原因
同一层:L12 数据库
其他层中同样导致“连不上/无限加载”的原因
查看含图示和实验的原卡片