ゲームラグ白書 › L12 データベース
サービス中のスキーマ変更(DDL)によるロック Schema change lock (DDL / metadata lock)
原因ID db-ddl-lock · 主担当 インフラチーム・DBインフラ · 副担当 ゲーム開発チーム・サーバー開発
図と実験のあるメインページでこのカードを開く →
サービス中にテーブルへカラムやインデックスを追加すると、一瞬だけ必要なロック1つのために、そのテーブルを使うすべての要求が待たされることがあります。
なぜ ホットフィックスでサービス中のテーブルにカラム・インデックスを追加 → すると スキーマ変更が先に開いていた長いトランザクションを待ち、後から来るすべての要求はそのスキーマ変更を待つ → 画面では そのテーブルを使う機能(インベントリ、郵便など)が丸ごと止まり、タイムアウト
- 症状
- 入力遅延, 不発・ロールバック, 接続不可・無限ロード
- 要因
- ストール
- 誰に起きるか
- 特定の機能だけ, サーバー全体
- いつ
- ときどきランダムに, 接続直後・メンテ明け
- 担当
- 主担当 インフラチーム・DBインフラ · 副担当 ゲーム開発チーム・サーバー開発
- ゲーム開発チームの対応
- スキーマ変更を含むホットフィックスはDBインフラと日程を調整、新しいカラムがなくても動くコードを先にデプロイ。
- インフラチームの対応
- ロック待ちの上限を短く設定し、失敗したら再試行、長いトランザクションがないときに実行、オンラインスキーマ変更ツールの使用、大きなテーブルはメンテナンス時間に。
- グラフでは
- ある時点から階段状に上昇 · ロック待ちのセッション数、そのテーブルのクエリ遅延
- 確認箇所
- MySQLはSHOW PROCESSLISTでStateがWaiting for table metadata lockのセッションを数え、sys.schema_table_lock_waitsでブロックしているセッション(blocking_pid)を探す。PostgreSQLはpg_locksでgrantedがfalseの要求とAccessExclusiveLockを確認し、pg_blocking_pids()でブロックしているセッションを探す
- 該当する場合
- スキーマ変更を開始した時刻から、そのテーブルを使うすべてのクエリがロック待ちで積み上がり、先頭に終わっていないトランザクションかスキーマ変更のステートメントがある
- 該当しない場合
- 待ちが特定の行にだけ集中し、同じテーブルの他の行は問題なく処理されているなら、ホットスポット(db-hot-row)
- 確認手段
- インフラのツールで確認(ゲームコード不要)
- もっと詳しく
- MySQLはスキーマを変更するときにメタデータロックを、PostgreSQLは最も強いテーブルロックを短時間取ります。変更自体は一瞬で終わっても、先に終わっていないトランザクションが1つあると、その後ろにすべての要求が並んで待ちます。
出典
- Online DDL Performance and Concurrency MySQL
オンラインDDLでも完了時に排他メタデータロックが一瞬必要、長いトランザクションがあれば待ち、待っているロック要求が後続のすべてのトランザクションを止める - Server System Variables MySQL
lock_wait_timeout:メタデータロック待ちの上限、デフォルト値は31,536,000秒(1年) - ALTER TABLE (PostgreSQL Documentation) PostgreSQL
特に記載のないALTER TABLEは、最も強いACCESS EXCLUSIVEロックを取る - Client Connection Defaults (PostgreSQL Documentation) PostgreSQL
lock_timeout:ロックをこの時間を超えて待つとステートメントを中断 - General Thread States MySQL
Waiting for table metadata lock:メタデータロックを待っているスレッドの状態 - The schema_table_lock_waits and x$schema_table_lock_waits Views MySQL
メタデータロックを待っているセッション(waiting_query)とブロックしているセッション(blocking_pid) - pg_locks (PostgreSQL Documentation) PostgreSQL
grantedがfalseならロック待ち、modeにAccessExclusiveLockなどのロックの種類 - System Information Functions and Operators (PostgreSQL Documentation) PostgreSQL
pg_blocking_pids():指定したセッションのロック取得をブロックしているセッションの一覧
あわせて読みたい原因
同じ層:L12 データベース
同じ症状(入力遅延)を起こすほかの層の原因
図と実験のあるメインページでこのカードを見る