遊戲 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)
- 確認方式
- 用基礎設施工具確認(不需要遊戲程式碼)
出處
- InnoDB Startup Options and System Variables MySQL
開啟偵測時(預設),InnoDB 會立即偵測死結並回滾;innodb_lock_wait_timeout 預設 50 秒 - Deadlock Detection MySQL
並行度極高時,偵測本身可能拖慢速度,因此有時會關閉偵測,改由鎖定等待上限處理 - Lock Management (PostgreSQL Documentation) PostgreSQL
deadlock_timeout 預設 1 秒:等待鎖定達到這個時間後才會檢查死結 - Deadlocks guide Microsoft SQL Server
死結檢查的預設間隔為 5 秒,死結頻繁時會縮短到 100ms;預設開啟的 system_health session 會收集 xml_deadlock_report;被犧牲的一方收到錯誤 1205 - How to Minimize and Handle Deadlocks MySQL
修改多筆資料列或多張資料表時一律依相同順序、失敗時重試、用 innodb_print_all_deadlocks 記錄所有死結 - InnoDB Standard Monitor and Lock Monitor Output MySQL
LATEST DETECTED DEADLOCK:最近一次死結的兩個 transaction、各自持有與等待的鎖定、被回滾的一方 - InnoDB INFORMATION_SCHEMA Metrics Table MySQL
INNODB_METRICS 的 lock_deadlocks 計數器(預設啟用) - Server Error Message Reference MySQL
1213 ER_LOCK_DEADLOCK(死結)、1205 ER_LOCK_WAIT_TIMEOUT(超過鎖定等待上限) - The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
pg_stat_database 的 deadlocks:此 DB 偵測到的死結次數 - PostgreSQL Error Codes (PostgreSQL Documentation) PostgreSQL
40P01 deadlock_detected
相關原因
同一層:L12 資料庫
同一症狀(吃指令/回檔)在其他層的原因
查看含圖解與實驗的完整版卡片