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

游戏卡顿白皮书 › L12 数据库

DB 死锁 Database deadlock

原因 ID db-deadlock · 主责 研发团队·服务器开发 · 配合 运维团队·数据库运维

在含图示和实验的完整版中打开此卡片 →

两个事务(作为一个整体处理的一组 DB 操作)互相等待对方锁住的行时,DB 会强制取消其中一个。

起因 交易 A 按物品→货币的顺序加锁,B 按货币→物品的顺序加锁 → 结果 DB 检测到死锁,回滚其中一方 → 画面表现 交易、制作偶尔失败,物品回退

症状
吞操作/回档, 操作延迟
因素
丢包, 停顿
谁会遇到
仅特定功能
何时出现
人多的时候, 做特定操作时
负责方
主责 研发团队·服务器开发 · 配合 运维团队·数据库运维
研发团队要做的事
统一加锁顺序,缩短事务,失败时自动重试。
运维团队要做的事
保持死锁检测开启,收集死锁记录并共享;关闭了检测的 MySQL 服务器要调低锁等待超时(默认 50 秒)。
数值参考
检测所需时间:MySQL(InnoDB)几乎即时,PostgreSQL 默认 1 秒,SQL Server 最多约 5 秒。在此期间两个请求都停在原地。如果服务器因并发请求极多而关闭了 MySQL 的死锁检测,就要一直等到锁等待超时(默认 50 秒)。
监控图上
偶发随机尖峰 · 死锁次数、交易失败次数
查看位置
MySQL 看 SHOW ENGINE INNODB STATUS 的 LATEST DETECTED DEADLOCK(最近 1 次),开启 innodb_print_all_deadlocks 后写入错误日志的所有死锁,以及 INFORMATION_SCHEMA.INNODB_METRICS 的 lock_deadlocks。PostgreSQL 看 pg_stat_database 的 deadlocks,SQL Server 看默认开启的 system_health 会话中的 xml_deadlock_report。游戏服务器侧的错误码为 MySQL 1213、PostgreSQL 40P01、SQL Server 1205
确认依据
交易、制作失败的时刻死锁次数增加,记录下的两个事务以相反的顺序锁同一组表
排除依据
死锁次数不变却失败,看锁等待超时(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 秒,死锁频繁时缩短到 100 ms;默认开启的 system_health 会话收集 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:最近一次死锁的两个事务、各自持有和等待的锁,以及被回滚的一方
  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:该数据库中检测到的死锁次数
  10. PostgreSQL Error Codes (PostgreSQL Documentation) PostgreSQL
    40P01 deadlock_detected

相关原因

同一层:L12 数据库

其他层中同样导致“吞操作/回档”的原因

查看含图示和实验的原卡片