한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

游戏卡顿白皮书 › L12 数据库

登录激增与 N+1 查询 Login storm, N+1 queries

原因 ID db-login-storm · 主责 研发团队·服务器开发 · 配合 运维团队·数据库运维

在含图示和实验的完整版中打开此卡片 →

加载一个角色要分别查询几十次时,数万人同时登录就会变成几百万条查询。

起因 加载角色时分别查询物品、技能、任务 → 结果 维护结束后大量玩家同时登录,查询激增 → 画面表现 登录时无限加载,正在游戏的玩家存盘也被拖慢

症状
连不上/无限加载, 操作延迟
因素
停顿, 延迟
谁会遇到
全服
何时出现
刚登录/维护结束后
负责方
主责 研发团队·服务器开发 · 配合 运维团队·数据库运维
研发团队要做的事
合并成一次查询,登录排队,缓存,检查 ORM 懒加载产生的查询次数。
运维团队要做的事
统计调用次数最多的查询排名并共享,监控维护结束后登录时段的查询数和连接数。
监控图上
开服/维护后激增 · DB 每秒查询数、登录数
查看位置
把维护结束后的登录数与 DB 每秒查询数(MySQL 看 Questions 的增量)叠加对照,算出每次登录的查询数。调用次数靠前的查询,MySQL 用 events_statements_summary_by_digest 的 COUNT_STAR,PostgreSQL 用 pg_stat_statements 的 calls 统计
确认依据
每次登录有几十条查询,排名靠前的是按单个角色 ID 查询的同类短查询。版本更新后每次登录的查询数增加,就从那次更新查起
排除依据
每次登录的查询数不多、但每条查询都慢,看“冷缓存(刚重启时)”(db-cold-cache)或“缺少索引的查询”(db-no-index)
确认手段
运维工具即可确认(无需游戏代码)
深入了解
ORM(代替开发者生成 DB 查询的库)的懒加载,会在开发者不知情的情况下产生这类查询。开发服上只有几个角色,看不出来,到线上大量玩家同时登录时才第一次暴露。

出处

  1. Efficient Querying .NET
    ORM 的懒加载会造成每个条目都多发一次查询的 N+1 问题,严重拖累性能;建议一次性批量加载(eager loading)
  2. pg_stat_statements — track statistics of SQL planning and execution PostgreSQL
    汇总每条语句的执行次数(calls)和总执行时间,得出调用最多的查询排名
  3. Performance Schema Statement Digests and Sampling MySQL
    用 events_statements_summary_by_digest 把同类查询归并,统计次数和时间
  4. Statement Summary Tables MySQL
    汇总表的 COUNT_STAR(执行次数)、SUM_TIMER_WAIT(总时间)
  5. Server Status Variables MySQL
    Questions:客户端发送的语句数

相关原因

同一层:L12 数据库

其他层中同样导致“连不上/无限加载”的原因

查看含图示和实验的原卡片