คู่มือเกมแลค › 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) วิธีตรวจ ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
แหล่งอ้างอิง 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 วินาทีตามค่าเริ่มต้น ถ้าเกิดเดดล็อกบ่อยจะลดลงได้ถึง 100 ms, เซสชัน system_health ที่เปิดไว้เป็นค่าเริ่มต้นเก็บ 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: สองทรานแซกชันของเดดล็อกล่าสุด, ล็อกที่ถือและที่รอ และฝั่งที่ถูกโรลแบ็ค InnoDB INFORMATION_SCHEMA Metrics Table MySQL ตัวนับ lock_deadlocks ใน INNODB_METRICS (เปิดใช้เป็นค่าเริ่มต้น) Server Error Message Reference MySQL 1213 ER_LOCK_DEADLOCK (เดดล็อก), 1205 ER_LOCK_WAIT_TIMEOUT (รอล็อกเกินขีดจำกัด) The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL deadlocks ใน pg_stat_database: จำนวนเดดล็อกที่ตรวจพบใน DB นี้ PostgreSQL Error Codes (PostgreSQL Documentation) PostgreSQL 40P01 deadlock_detected
สาเหตุที่ควรดูประกอบ
ชั้นเดียวกัน: L12 ฐานข้อมูล
สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (กดไม่ติด/โรลแบ็ค)
ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง