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

遊戲 Lag 白皮書 › L12 資料庫

DB 死結 Database deadlock

原因 ID db-deadlock · 主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(DB 基礎設施)

在含圖解與實驗的完整版中開啟卡片 →

兩個 transaction(當成一個整體處理的一組 DB 操作)互相等待對方鎖住的資料列時,DB 會強制取消其中一方。

為什麼 交易 A 依道具 → 貨幣的順序鎖定,交易 B 依貨幣 → 道具的順序鎖定 → 於是 DB 偵測到死結,回滾其中一方 → 畫面上 交易、製作偶爾失敗,道具被退回

症狀
吃指令/回檔, 輸入延遲
因素
遺失, 停滯
誰會遇到
只有特定功能
何時
人潮湧入時, 做特定動作時
負責單位
主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(DB 基礎設施)
遊戲開發團隊要做的事
統一鎖定順序、縮短 transaction、失敗時自動重試。
基礎設施團隊要做的事
保持死結偵測開啟,收集並分享死結紀錄;關閉偵測的 MySQL 伺服器要調低鎖定等待上限(預設 50 秒)。
數值參考
偵測所需時間:MySQL(InnoDB)幾乎即時,PostgreSQL 預設 1 秒,SQL Server 最多約 5 秒。這段期間兩個請求都會卡住。如果是因同時請求極多而關閉 MySQL 死結偵測的伺服器,會一直等到鎖定等待上限(預設 50 秒)。
圖表上
偶爾隨機飆高 · 死結次數、交易失敗次數
查看位置
MySQL 看 SHOW ENGINE INNODB STATUS 的 LATEST DETECTED DEADLOCK(只有最近 1 筆)、開啟 innodb_print_all_deadlocks 後寫入錯誤 log 的所有死結,以及 INFORMATION_SCHEMA.INNODB_METRICS 的 lock_deadlocks。PostgreSQL 看 pg_stat_database 的 deadlocks,SQL Server 看預設開啟的 system_health session 的 xml_deadlock_report。遊戲伺服器端的錯誤碼為 MySQL 1213、PostgreSQL 40P01、SQL Server 1205
符合的跡象
交易、製作失敗的時間點死結次數增加,紀錄中的兩個 transaction 以相反的順序鎖定相同的資料表
不符合的跡象
死結次數不變卻仍失敗時,是超過鎖定等待上限(MySQL 錯誤 1205)或熱點資料列(db-hot-row)
確認方式
用基礎設施工具確認(不需要遊戲程式碼)

出處

  1. InnoDB Startup Options and System Variables MySQL
    開啟偵測時(預設),InnoDB 會立即偵測死結並回滾;innodb_lock_wait_timeout 預設 50 秒
  2. Deadlock Detection MySQL
    並行度極高時,偵測本身可能拖慢速度,因此有時會關閉偵測,改由鎖定等待上限處理
  3. Lock Management (PostgreSQL Documentation) PostgreSQL
    deadlock_timeout 預設 1 秒:等待鎖定達到這個時間後才會檢查死結
  4. Deadlocks guide Microsoft SQL Server
    死結檢查的預設間隔為 5 秒,死結頻繁時會縮短到 100ms;預設開啟的 system_health session 會收集 xml_deadlock_report;被犧牲的一方收到錯誤 1205
  5. How to Minimize and Handle Deadlocks MySQL
    修改多筆資料列或多張資料表時一律依相同順序、失敗時重試、用 innodb_print_all_deadlocks 記錄所有死結
  6. InnoDB Standard Monitor and Lock Monitor Output MySQL
    LATEST DETECTED DEADLOCK:最近一次死結的兩個 transaction、各自持有與等待的鎖定、被回滾的一方
  7. InnoDB INFORMATION_SCHEMA Metrics Table MySQL
    INNODB_METRICS 的 lock_deadlocks 計數器(預設啟用)
  8. Server Error Message Reference MySQL
    1213 ER_LOCK_DEADLOCK(死結)、1205 ER_LOCK_WAIT_TIMEOUT(超過鎖定等待上限)
  9. The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
    pg_stat_database 的 deadlocks:此 DB 偵測到的死結次數
  10. PostgreSQL Error Codes (PostgreSQL Documentation) PostgreSQL
    40P01 deadlock_detected

相關原因

同一層:L12 資料庫

同一症狀(吃指令/回檔)在其他層的原因

查看含圖解與實驗的完整版卡片