ゲームラグ白書 › L12 データベース
大規模なバッチ処理 Batch jobs during service
原因ID db-batch · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ
図と実験のあるメインページでこのカードを開く →
ランキング集計、郵便の一括送信、古いデータの整理をサービス中に実行すると、ロックとディスクを占有します。
なぜ サービス時間中に大量の処理を実行 → すると 広い範囲のロック、ディスク・CPUの占有 → 画面では 特定の時間帯に取引・保存が失敗、ロード遅延
- 症状
- 入力遅延, 不発・ロールバック
- 要因
- 遅延, ストール
- 誰に起きるか
- 特定の機能だけ, サーバー全体
- いつ
- 一定の周期で
- 担当
- 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ
- ゲーム開発チームの対応
- 細かく分けて少しずつ、集計はレプリカで。
- インフラチームの対応
- 集計用レプリカの提供、バッチは空いている時間帯に予約、ロックエスカレーション・ギャップロック待ちの監視。
- グラフでは
- 周期的なスパイク · DBクエリの遅延、ロック待ち
- 確認箇所
- ラグが出た時刻に動いていた長いクエリを探す。MySQLはslow query log、PostgreSQLはpg_stat_activityのquery_start・queryを確認し、同じ時刻のロック待ちのメトリクスとバッチのスケジュール(cron、DBのイベントスケジューラー)を照合。SQL Serverはlock_escalation拡張イベントでロックエスカレーションを記録
- 該当する場合
- 毎回同じ時刻に大量のUPDATE・DELETE・集計クエリが動き、その間ロック待ちとディスク利用率がそろって上がる
- 該当しない場合
- その時刻に長いクエリがなければ、チェックポイント(db-checkpoint)かサーバーのバックアップ(dk-backup)
- 確認手段
- インフラのツールで確認(ゲームコード不要)
- もっと詳しく
- SQL Serverは、1つのステートメントが約5,000個を超える行ロックを取ると、テーブルロックに切り替えます(ロックエスカレーション)。その瞬間、同じテーブルを使うすべての要求が止まります。MySQLもデフォルト設定では、範囲条件で更新すると行と行の間の隙間までロックし(ギャップロック)、新しい行の挿入を止めます。
出典
- Transaction Locking and Row Versioning Guide Microsoft SQL Server
1つのステートメントが1つのテーブル(またはインデックス)で5,000個以上のロックを取るとロックエスカレーション、lock_escalation拡張イベントで記録 - InnoDB Locking MySQL
InnoDBのデフォルトの分離レベルREPEATABLE READでは、検索・スキャンにnext-keyロックを使うため、ギャップロックがその隙間への新しい行の挿入を止める - The Slow Query Log MySQL
long_query_timeを超えたクエリを、実行時間(Query_time)・ロック時間(Lock_time)・読んだ行数とともに記録 - The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
pg_stat_activity:セッションごとの現在実行中のクエリ(query)と開始時刻(query_start)
あわせて読みたい原因
同じ層:L12 データベース
同じ症状(入力遅延)を起こすほかの層の原因
図と実験のあるメインページでこのカードを見る