Upgrade to Pro — share decks privately, control downloads, hide ads and more …

【TiDB GAME DAY 2025】Shadowverse: Worlds Beyond ...

Avatar for Cygames Cygames
June 25, 2025

【TiDB GAME DAY 2025】Shadowverse: Worlds Beyond にみる TiDB 活用術

2025/05/30 TiDB Game Day 2025

Avatar for Cygames

Cygames

June 25, 2025
Tweet

More Decks by Cygames

Other Decks in Technology

Transcript

  1. 1/72 TiDB GAME DAY 2025 Shadowverse: Worlds Beyond にみる TiDB

    活用術 株式会社 Cygames サーバーサイド 宮脇 剛史
  2. 4/72 Shadowverse: Worlds Beyond について 2025 年 6 月 17

    日 (火) リリース 現在事前登録受付中
  3. 6/ 自己紹介 宮脇 剛史 シニアゲームエンジニア / サーバーサイド サーバーサイドエンジニアとして 複数のタイトルでの運用を経て、 現在はサーバータスクにて横断的な技術支援、

    技術検証、負荷試験などを担当。 直近では『Shadowverse: Worlds Beyond』などの TiDB 導入や技術支援を担当し、 大規模データ処理とパフォーマンス最適化を実現。
  4. 8/72 Shadowverse: Worlds Beyond への支援 – TiDB テーブル設計ガイドラインの共有 – データベースの問題発生時の調査

    – テーブル設計、クエリ、ソースコードのレビュー – 負荷試験の実施 サーバータスクチームについて
  5. 9/72 1. TiDB 採用に至るまでの検証 2. Shadowverse: Worlds Beyond の TiDB

    活用術 – API サーバ実装 – データ運用 – データ分析 3. Shadowverse: Worlds Beyond の負荷試験 4. まとめ アジェンダ
  6. 14/72 Cygames では、 TiDB の導入判断のため 2021 年ごろから検証を開始 MySQL との比較や TiDB

    の特性の把握を目的として 機能検証 や 性能検証 を実施 Cygames における TiDB の検証
  7. 27/72 MySQL では REPEATABLE READ を使っていた TiDB で 同じように REPEATABLE

    READ を使うと Lost Update が発生する場合がある TiDB では READ COMMITTED を採用 トランザクション分離レベルの工夫
  8. 29/72 Lost Update TX1 TX2 BEGIN; SELECT value FROM user_items

    WHERE user_id=1 AND item_id=1; value: 1 を取得 UPDATE user_items SET value=10 WHERE user_id=1; value: 10 に更新 UPDATE user_items SET value=1+1 WHERE user_id=1 AND item_id=1; value: 2 に上書き Lost Update COMMIT;
  9. 30/72 Lost Update の回避 TX1 TX2 BEGIN; SELECT * FROM

    users WHERE id=1 FOR UPDATE; ロック用テーブルで ロック SELECT value FROM user_items WHERE user_id=1 AND item_id=1; value: 1 を取得 BEGIN; SELECT * FROM users WHERE id=1 FOR UPDATE; ロック待ちとなり 更新できない UPDATE user_items SET value=1+1 WHERE user_id=1 AND item_id=1; value: 2 に更新 COMMIT;
  10. 31/72 MySQL では REPEATABLE READ のスナップショットは 最初の SELECT を実行したタイミングで取得 SELECT

    したテーブル以外のデータも同時にスナップショット 排他処理の前に意図せず SELECT をして事故が起きるケースも トランザクション開始直後に排他処理という ルールを守っていれば問題なかった MySQL のスナップショット
  11. 32/72 MySQL のスナップショット TX1 TX2 BEGIN; UPDATE user_items SET value=10

    WHERE user_id=1; value: 10 に更新 SELECT * FROM users WHERE id=1; ユーザー情報取得 スナップショット UPDATE user_items SET value=20 WHERE user_id=1; value: 20 に更新 SELECT value FROM user_items WHERE user_id=1 AND item_id=1; スナップショットか ら value: 10 を取得 COMMIT;
  12. 34/72 TiDB での Lost Update TX1 TX2 BEGIN; スナップショット BEGIN;

    SELECT * FROM users WHERE id=1 FOR UPDATE; UPDATE user_items SET value=10 WHERE user_id=1; value: 10 に更新 COMMIT; SELECT * FROM users WHERE id=1 FOR UPDATE; ユーザー情報取得 SELECT value FROM user_items WHERE user_id=1 AND item_id=1; スナップショットか ら value: 1 を取得 UPDATE user_items SET value=1+1 WHERE user_id=1 AND item_id=1; value: 2 に上書き Lost Update COMMIT;
  13. 35/72 TiDB で Lost Update が発生する問題の対策を検討 1. GET_LOCK / RELEASE_LOCK

    を使う 2. 更新に関係する SELECT 全てに FOR UPDATE を付ける 3. READ COMMITTED を使う TiDB での Lost Update
  14. 37/72 TX1 TX2 SELECT GET_LOCK('users:1', 60); ロック BEGIN; スナップショット SELECT

    GET_LOCK('users:1', 60); ロック待ち SELECT * FROM users WHERE id=1 FOR UPDATE; ユーザー情報取得 SELECT value FROM user_items WHERE user_id=1 AND item_id=1; スナップショットか ら value: 1 を取得 UPDATE user_items SET value=1+1 WHERE user_id=1 AND item_id=1; value: 2 に更新 COMMIT; SELECT RELEASE_LOCK('users:1'); ロック解除 Lost Update 対策 1: GET_LOCK
  15. 39/72 Lost Update 対策 2: SELECT FOR UPDATE TX1 TX2

    BEGIN; スナップショット BEGIN; SELECT * FROM users WHERE id=1 FOR UPDATE; UPDATE user_items SET value=10 WHERE user_id=1; value: 10 に更新 COMMIT; SELECT * FROM users WHERE id=1 FOR UPDATE; ユーザー情報取得 SELECT value FROM user_items WHERE user_id=1 AND item_id=1 FOR UPDATE; 最新の value: 10 を 取得 UPDATE user_items SET value=10+1 WHERE user_id=1 AND item_id=1; value: 11 に更新 COMMIT;
  16. 40/72 REPEATABLE READ の必要性を再検討 – トランザクションの先頭で排他処理を行うため 他トランザクションから同時に更新されることはない – ファジーリードを気にする必要がない –

    REPEATABLE READ である必要性がない READ COMMITTED を使うことで SELECT は最新データを取得することができる Lost Update 対策 3: READ COMMITTED
  17. 41/72 TX1 TX2 BEGIN; BEGIN; SELECT * FROM users WHERE

    id=1 FOR UPDATE; UPDATE user_items SET value=10 WHERE user_id=1; value: 10 に更新 COMMIT; SELECT * FROM users WHERE id=1 FOR UPDATE; ユーザー情報取得 SELECT value FROM user_items WHERE user_id=1 AND item_id=1; 最新の value: 10 を 取得 UPDATE user_items SET value=10+1 WHERE user_id=1 AND item_id=1; value: 11 に更新 COMMIT; Lost Update 対策 3: READ COMMITTED
  18. 42/72 Lost Update 回避方法ごとの性能 (TPS) を比較 シナリオ 1. ユーザー単位でロック 2.

    そのユーザーのアイテム全 100 件取得 3. その内 1 件を更新 TiDB における Lost Update 対策の性能比較
  19. 43/72 TiDB における Lost Update 対策の性能比較 Aurora db.r8g.8xlarge TiDB Cloud

    TiDB: 8 vCPU, 16 GiB * 2 TiKV: 8 vCPU, 32 GiB * 3 パフォーマンスが良く、対応も容易な READ COMMITED を採用
  20. 44/72 • テーブル・クエリ設計 効率の良い参照ができるように プライマリキーやインデックスを設計する • トランザクション分離レベル MySQL と TiDB

    でスナップショットを取得する タイミングが異なるため Lost Update の可能性がある READ COMMITTED を採用することで回避 API サーバ実装の工夫まとめ
  21. 52/72 これらのクエリは TiDB でエラーになる可能性がある – 大量のデータをまとめて更新 UPDATE {table} SET value

    = 100; – データの一括削除 DELETE FROM {table}; – テーブルのメンテナンスのためのデータコピー INSERT INTO {table_new} SELECT * FROM {table_old}; トランザクションサイズにより失敗する例
  22. 53/72 TiDBがクエリを自動で分割して実行する BATCH ON id LIMIT 1000 DELETE FROM users;

    このクエリは以下のように分割、順次実行される DELETE FROM users WHERE id BETWEEN 1 AND 1000; DELETE FROM users WHERE id BETWEEN 1001 AND 2000; 対策 1: Non-Transactional DML ︙
  23. 60/72 DELETE による消し込み • create_time や delete_time が一定期間より 前のものを削除する DELETE

    クエリを毎日実行 削除対象を検索したり、ストレージに書き込むため データ量の多いテーブルでは TiDB や TiKV の負荷が大きい
  24. 61/72 TTL による消し込み • create_time や delete_time に TTL を設定

    • 一定時間ごとに自動的に TTL ジョブが実行 • TTLジョブは内部的に SELECT や DELETE を実行し、 データを削除 DELETE による消し込みと同様 TiDB, TiKV の負荷が大きい
  25. 62/72 パーティションドロップによる消し込み • create_time や delete_time で 日ごとのパーティションを作成 • パーティションドロップのクエリを毎日実行

    他の方法とは異なり TiKV のレイヤーでまとめて削除できるので軽量かつ高速 MySQL と同様にパーティションドロップを採用
  26. 66/72 分析基盤: Snowflake 社内共通の分析基盤として Snowflake が既にある 容量確保のため、多くのログデータは S3 上に保存 TiFlash

    を導入しても分析に必要なデータがない Changefeed は使用せず、別途 ETL サーバを用意 Snowflake上のデータがリアルタイムで更新されると 今までと同じような分析がしづらくなる
  27. 71/72 • 検証から得た知見を元に TiDB の活用術を構築 – 最高のコンテンツを作るため、自分たちが使うツールは 時間を掛けてでも検証し、仕組みを理解して、活用する – Cygames

    は今後も TiDB をデータベースの第一の選択肢として 積極的に取り組んでいく • TiDB を採用した Shadowverse: Worlds Beyond は 6 月 17 日リリース まとめ