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

คู่มือเกมแลค › L12 ฐานข้อมูล

เดดล็อกใน DB Database deadlock

ID สาเหตุ db-deadlock · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)

เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →

ถ้าสองทรานแซกชัน (งาน DB ที่ประมวลผลเป็นชุดเดียว) ต่างรอแถวที่อีกฝ่ายล็อกไว้ DB จะบังคับยกเลิกฝั่งหนึ่ง

ทำไม การเทรด A ล็อกตามลำดับไอเทม→เงินในเกม ส่วน B ล็อกตามลำดับเงินในเกม→ไอเทม → ผลคือ DB ตรวจพบเดดล็อกแล้วโรลแบ็คฝั่งหนึ่ง → บนหน้าจอ เทรดและคราฟต์ล้มเหลวเป็นบางครั้ง, ไอเทมย้อนกลับ

อาการ
กดไม่ติด/โรลแบ็ค, อินพุตดีเลย์
ปัจจัย
แพ็กเก็ตหาย, การหยุดชะงัก
ใครเจอ
เฉพาะบางฟีเจอร์
เกิดเมื่อไร
ตอนคนแห่มารวมกัน, ตอนทำแอ็กชันบางอย่าง
ผู้รับผิดชอบ
ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม
ใช้ลำดับการล็อกเดียวกันทุกที่, ทำทรานแซกชันให้สั้น, ลองใหม่อัตโนมัติเมื่อล้มเหลว
งานฝั่งทีมอินฟรา
เปิดการตรวจจับเดดล็อกไว้และเก็บบันทึกเดดล็อกมาแชร์, เซิร์ฟเวอร์ MySQL ที่ปิดการตรวจจับให้ลดขีดจำกัดการรอล็อก (ค่าเริ่มต้น 50 วินาที)
ตัวเลขที่ควรรู้
MySQL (InnoDB) ตรวจพบได้แทบทันที PostgreSQL ใช้เวลา 1 วินาทีตามค่าเริ่มต้น และ SQL Server ใช้นานสุดราว 5 วินาที ระหว่างนั้นคำขอทั้งสองหยุดรออยู่ ถ้าเป็นเซิร์ฟเวอร์ MySQL ที่ปิดการตรวจจับไว้เพราะคำขอพร้อมกันมากเป็นพิเศษ จะต้องรอจนถึงขีดจำกัดการรอล็อก (ค่าเริ่มต้น 50 วินาที)
บนกราฟ
พุ่งแบบสุ่มเป็นครั้งคราว · จำนวนเดดล็อก, จำนวนการเทรดที่ล้มเหลว
จุดที่ต้องดู
MySQL ดู LATEST DETECTED DEADLOCK ใน SHOW ENGINE INNODB STATUS (เฉพาะรายการล่าสุด 1 รายการ), เดดล็อกทั้งหมดที่บันทึกใน error log เมื่อเปิด innodb_print_all_deadlocks และ lock_deadlocks ใน INFORMATION_SCHEMA.INNODB_METRICS ส่วน PostgreSQL ดู deadlocks ใน pg_stat_database และ SQL Server ดู xml_deadlock_report ของเซสชัน system_health ที่เปิดไว้เป็นค่าเริ่มต้น รหัสข้อผิดพลาดฝั่งเซิร์ฟเวอร์เกมคือ MySQL 1213, PostgreSQL 40P01, SQL Server 1205
สัญญาณว่าใช่
ช่วงที่เทรดหรือคราฟต์ล้มเหลว จำนวนเดดล็อกเพิ่มขึ้น และสองทรานแซกชันที่บันทึกไว้ล็อกตารางชุดเดียวกันในลำดับตรงข้ามกัน
สัญญาณว่าไม่ใช่
จำนวนเดดล็อกเท่าเดิมแต่ยังล้มเหลว: น่าจะเป็นการรอล็อกเกินขีดจำกัด (MySQL ข้อผิดพลาด 1205) หรือ hot row (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
    ตัวนับ lock_deadlocks ใน INNODB_METRICS (เปิดใช้เป็นค่าเริ่มต้น)
  8. Server Error Message Reference MySQL
    1213 ER_LOCK_DEADLOCK (เดดล็อก), 1205 ER_LOCK_WAIT_TIMEOUT (รอล็อกเกินขีดจำกัด)
  9. The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
    deadlocks ใน pg_stat_database: จำนวนเดดล็อกที่ตรวจพบใน DB นี้
  10. PostgreSQL Error Codes (PostgreSQL Documentation) PostgreSQL
    40P01 deadlock_detected

สาเหตุที่ควรดูประกอบ

ชั้นเดียวกัน: L12 ฐานข้อมูล

สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (กดไม่ติด/โรลแบ็ค)

ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง