FiveM MariaDB Deadlock คืออะไร? วิธีแก้ Deadlock Found When Trying to Get Lock และลด Transaction ชนกัน
FiveM MariaDB Deadlock คือสถานการณ์ที่ Transactions ตั้งแต่ 2 ชุดขึ้นไปถือ Locks คนละส่วน แล้วต่างฝ่ายต่างรอ Lock ที่อีกฝ่ายถืออยู่จนไม่มี Transaction ใดสามารถเดินหน้าต่อได้ตามปกติ MariaDB ใช้ Error 1213 หรือ ER_LOCK_DEADLOCK พร้อมข้อความ Deadlock found when trying to get lock; try restarting transaction.
สำหรับ FiveM Server ที่ใช้ oxmysql ปัญหานี้มักเกี่ยวข้องกับ Resource หลายตัวหรือหลาย Requests ที่แก้ข้อมูลชุดเดียวกันพร้อมกัน โดยเฉพาะเมื่อ Transactions ล็อก Rows/Tables ในลำดับไม่เหมือนกัน
จำง่ายๆ:
Transaction A
ล็อก Row 1
↓
ต้องการ Row 2
Transaction B
ล็อก Row 2
↓
ต้องการ Row 1
A รอ B
B รอ A
= Deadlock
สิ่งที่ไม่ควรทำคือเห็น Error แล้วเพิ่ม Timeout อย่างเดียว เพราะ Deadlock ไม่ใช่แค่การรอนาน แต่เป็นวงจรที่ Transactions รอกันเอง
① Deadlock คืออะไร
ตัวอย่างง่ายที่สุด:
Transaction A:
Lock Player A
↓
ต้องการ Player B
Transaction B:
Lock Player B
↓
ต้องการ Player A
เกิดวงจร:
A → รอ B
B → รอ A
จึงไม่มีฝ่ายใดไปต่อได้หาก Database ไม่เข้ามาจัดการ
InnoDB มี Deadlock Detector เปิดใช้งานเป็นค่าเริ่มต้น และสามารถตรวจ Deadlock เพื่อยุติวงจรได้.
② Error 1213 คืออะไร
MariaDB ระบุ Error:
ERROR 1213 (40001)
Deadlock found when trying to get lock;
try restarting transaction
โดยชื่อ Error คือ:
ER_LOCK_DEADLOCK
และ SQLSTATE คือ:
40001
ดังนั้นหาก oxmysql Console แสดงข้อความลักษณะนี้ ให้ตรวจ Transaction และ Locks ก่อน ไม่ใช่ Connection String
③ Deadlock ไม่ได้แปลว่า Database พัง
Deadlock สามารถเกิดได้ในระบบ Transactional Database ที่มี Concurrent Writes
ตัวอย่าง:
Request 1
UPDATE A
UPDATE B
เกิดพร้อม:
Request 2
UPDATE B
UPDATE A
แม้ SQL ทั้งสองชุดจะถูก Syntax แต่ Order ที่สวนกันสามารถสร้าง Lock Cycle ได้
ดังนั้น Deadlock เป็นปัญหา:
Concurrency
+
Transaction Design
ไม่ใช่เพียง Database Connection Error
④ Deadlock ต่างจาก Lock Wait Timeout อย่างไร
Deadlock
A รอ B
B รอ A
เป็นวงจร
Lock Wait Timeout
A ถือ Lock
B รอ A
แต่ A ไม่จำเป็นต้องรอ B
MariaDB มี Deadlock Detection แยกจาก innodb_lock_wait_timeout; หากปิด Deadlock Detector MariaDB จะต้องพึ่ง Lock Wait Timeout มากขึ้น.
⑤ Deadlock Detector คืออะไร
MariaDB มีตัวแปร:
innodb_deadlock_detect
เอกสารระบุว่าเปิดเป็น Default และถ้าปิด ระบบตรวจ Deadlock จะไม่ทำงาน โดย MariaDB จะพึ่ง innodb_lock_wait_timeout แทนมากขึ้น.
สำหรับ FiveM Server ทั่วไปไม่ควรปิด Deadlock Detection เพื่อแก้ปัญหา Deadlock โดยไม่ได้ Benchmark และเข้าใจ Workload จริง
⑥ MariaDB ทำอะไรเมื่อเจอ Deadlock
เมื่อ InnoDB ตรวจพบวงจร Deadlock ระบบต้องทำลายวงจรโดย Rollback Transaction หนึ่งชุด เพื่อให้ Transaction อื่นสามารถเดินหน้าต่อได้
SHOW ENGINE INNODB STATUS สามารถแสดง Deadlock, Statements, Locks ที่ถือ/ต้องการ และ Transaction ที่ถูก Rollback ได้.
ดังนั้น Error 1213 จึงมีข้อความแนะนำ:
try restarting transaction
⑦ Retry Transaction คืออะไร
หมายถึง Application สามารถออกแบบให้ Operation ที่เจอ Deadlock ลองทำ Transaction ใหม่อีกครั้งหลัง Transaction เดิมถูกยุติ
แนวคิด:
Transaction
↓
Deadlock
↓
Rollback
↓
Retry
↓
Success
แต่ Retry ต้องทำอย่างระมัดระวัง
ไม่ใช่:
while true do
retry()
end
เพราะถ้า Root Cause ยังอยู่ อาจกลายเป็น Retry Loop
⑧ Retry Deadlock ควรจำกัดจำนวนครั้ง
ตัวอย่างแนวคิด:
Attempt 1
↓
Deadlock
Attempt 2
↓
Deadlock
Attempt 3
↓
หยุด + Log Error
จำนวนจริงต้องออกแบบตาม Resource และ Business Operation
เป้าหมายคือรองรับ Deadlock ชั่วคราว ไม่ใช่ซ่อน Transaction Design ที่ผิด
⑨ Retry ต้องระวัง Side Effect
สมมติ Transaction Database Fail แต่ก่อนหน้า Code ทำ:
ส่ง Event
ให้ Item
เปลี่ยน Cache
ส่ง Notification
แล้ว Retry Transaction
อาจเกิด:
Side Effect ซ้ำ
ดังนั้น Operation ที่ Retry ได้ควรถูกออกแบบให้ Database Transaction และ Application State มีความสอดคล้อง
⑩ oxmysql Transaction คืออะไร
oxmysql มี MySQL.transaction ซึ่งใช้ Execute หลาย Queries และ Commit เฉพาะเมื่อ Queries ทั้งหมดสำเร็จ หากหนึ่ง Query ล้มเหลว Transaction จะไม่ Commit ตามปกติ.
ตัวอย่าง:
local success = MySQL.transaction.await({
{
query = [[
UPDATE `player_profiles`
SET `status` = ?
WHERE `id` = ?
]],
values = {
'active',
profileId
}
},
{
query = [[
UPDATE `player_settings`
SET `updated_at` = NOW()
WHERE `profile_id` = ?
]],
values = {
profileId
}
}
})
Transaction มีประโยชน์กับ Consistency แต่ต้องออกแบบ Lock Order ให้ดี
⑪ Transaction ใหญ่เกินไปเพิ่มความเสี่ยง Deadlock
สมมติ Transaction ทำ:
UPDATE Table A
UPDATE Table B
UPDATE Table C
UPDATE Table D
UPDATE Table E
ยิ่งแตะ Resources จำนวนมาก Transaction ก็อาจถือ Locks มากขึ้นและนานขึ้น
ดังนั้นอย่าเอา Queries ทุกอย่างมารวม Transaction เพียงเพราะคิดว่า:
Transaction ใหญ่ = ปลอดภัยกว่า
ควรรวมเฉพาะ Operations ที่ต้อง Commit หรือ Rollback พร้อมกันจริง.
⑫ Transaction ควรสั้น
แนวทางที่ดี:
เตรียมข้อมูล
↓
Validate
↓
เริ่ม Transaction
↓
Execute SQL
↓
Commit
หลีกเลี่ยง:
เริ่ม Transaction
↓
Query
↓
Wait
↓
เรียก Network
↓
รอ Client
↓
Query
↓
Commit
เพราะช่วงเวลาที่ Transaction เปิดอยู่ยิ่งนาน โอกาสเกิด Lock Contention ก็ยิ่งเพิ่ม
⑬ อย่ารอ Client Response ภายใน Transaction
ตัวอย่างที่ไม่ควรออกแบบ:
Begin Transaction
↓
Update Row
↓
Send Event to Client
↓
Wait Client Reply
↓
Update อีก Row
↓
Commit
Client อาจ:
Lag
Disconnect
ไม่ตอบ
ทำให้ Transaction อยู่ได้นานโดยไม่จำเป็น
ควรเก็บ/Validate Input ให้พร้อมก่อนเข้า Critical Transaction Section เมื่อทำได้
⑭ Lock Order คือหัวใจสำคัญ
หนึ่งในวิธีลด Deadlock ที่สำคัญคือให้ Transactions ที่แตะข้อมูลชุดเดียวกัน ล็อกหรือแก้ Records ในลำดับเดียวกัน
ตัวอย่างที่เสี่ยง:
Transaction A:
UPDATE profiles
↓
UPDATE settings
Transaction B:
UPDATE settings
↓
UPDATE profiles
ถ้าเกิดพร้อมกัน Transaction แต่ละตัวอาจถือ Lock ที่อีกฝ่ายต้องการ
⑮ เปลี่ยนให้ใช้ Order เดียวกัน
กำหนดมาตรฐาน:
① profiles
② settings
③ metadata
ทุก Resource ที่ต้องแก้ข้อมูลสามชุดนี้ควรทำ:
profiles
↓
settings
↓
metadata
เหมือนกัน
แทนให้แต่ละ Resource เลือกลำดับเอง
⑯ ตัวอย่าง Deadlock กับ Players 2 คน
Transaction A:
UPDATE player 100
↓
UPDATE player 200
Transaction B:
UPDATE player 200
↓
UPDATE player 100
หากทำพร้อมกัน:
A ถือ 100
B ถือ 200
A ต้องการ 200
B ต้องการ 100
เกิด Deadlock
⑰ แก้ด้วย Sorted Order ได้
ถ้า Operation ต้องแก้ Player IDs หลายตัว ให้จัดลำดับก่อน เช่น:
100
200
แล้วทุก Transaction ล็อก:
100
↓
200
เหมือนกัน
แทนใช้ Order ตาม Player ที่ Request เข้ามา
นี่เป็น Application-level Strategy ที่ช่วยลด Lock Cycle
⑱ Deadlock เกิดจาก Table เดียวได้ไหม
ได้
ไม่จำเป็นต้องมีหลาย Tables
เช่น:
players
Table เดียว แต่ Transactions ล็อก Rows ต่างกันและกลับมาเรียก Row ของกันและกัน ก็สามารถเกิด Deadlock ได้
ดังนั้นคำว่า:
Deadlock
ไม่ได้หมายความว่า Table ถูกล็อกทั้ง Table เสมอ
⑲ Hot Row คืออะไร
Hot Row คือ Row ที่มี Concurrent Writes จำนวนมาก
ตัวอย่าง:
server_stats
id = 1
Player ทุกคนทำ:
UPDATE `server_stats`
SET `online_actions` =
`online_actions` + 1
WHERE `id` = 1;
Row เดียวจึงถูกเขียนจากหลาย Requests
แม้ไม่เกิด Deadlock ทุกครั้ง แต่สามารถเพิ่ม Lock Contention อย่างมาก
⑳ Shared Global Row ต้องระวัง
ตัวอย่าง:
global_counter
global_state
server_statistics
ถ้าทุก Resource เขียน Row เดียว:
Player A
Player B
Player C
Player D
↓
Row เดียว
Database ต้อง Serialize Writes มากขึ้น
ควรตรวจว่าจำเป็นต้อง Persist ทุก Action จริงหรือไม่
㉑ Cache ช่วยลด Deadlock ได้ไหม
ช่วยลด Database Operations ที่ไม่จำเป็นได้
ตัวอย่าง:
Gameplay
↓
Update Memory Cache
เป็นระยะ
↓
Persist Database
แทน:
Gameplay Action ทุกครั้ง
↓
UPDATE Shared Row
แต่ข้อมูลที่ต้องการ Transactional Durability จริงยังควรถูกเขียนตาม Requirement
㉒ Dirty Flag ช่วยได้อย่างไร
ตัวอย่าง:
dirty = false
เมื่อ State เปลี่ยน:
dirty = true
ตอน Autosave:
dirty = false
→ Skip
dirty = true
→ Save
ช่วยลด Writes และ Lock Requests ที่ไม่จำเป็น
㉓ Autosave พร้อมกันทำให้ Deadlock เพิ่มไหม
สามารถเพิ่มโอกาสได้ถ้า Resource หลายตัว Update Records ชุดเดียวกันพร้อมกัน
ตัวอย่าง:
เวลา 18:00:00
Player 1 Save
Player 2 Save
Player 3 Save
...
Player 300 Save
พร้อม Resources อื่นที่กำลังแก้ Tables เดียวกัน
Concurrency สูงขึ้นจึงเพิ่มโอกาสเกิด Lock Contention
㉔ Stagger Autosave คืออะไร
แทน:
300 Players
↓
Save พร้อมกัน
กระจาย:
Player กลุ่ม 1
↓
Player กลุ่ม 2
↓
Player กลุ่ม 3
ตามช่วงเวลาที่เหมาะสม
ช่วยลด Write Burst
แต่ต้องออกแบบไม่ให้ Player Data สูญหายหาก Server Crash ระหว่างรอบ Save
㉕ Login Burst เกี่ยวข้องได้ไหม
หลัง Server Restart ผู้เล่นจำนวนมากอาจ Login พร้อมกัน
แต่ละ Resourceอาจทำ:
Create/Update Session
Load Character
Update Last Seen
Update Settings
Update Metadata
ถ้า Resource หลายตัว Update Rows เดียวกันใน Order ต่างกัน Deadlock สามารถเกิดเฉพาะช่วง Login Burst ได้
㉖ Query ช้าทำให้ Deadlock แย่ขึ้นได้อย่างไร
Query ช้าสามารถทำให้ Transaction ถือ Locks นานขึ้น
oxmysql ระบุว่าความเร็ว Query ควรตรวจจาก Debug UI หรือ Server Console ผ่าน mysql_debug และ Query Speed จะแตกต่างตาม Hardware, Database Settings, Version และ Workload.
ดังนั้นควรตรวจ:
Deadlock
+
Slow Query
ร่วมกัน
㉗ Index ไม่ดีมีผลไหม
Query ที่ค้นหา Rows ได้ไม่แม่นหรือใช้เวลานานสามารถขยายเวลา Transaction
ควรตรวจ Query Plan ด้วย:
EXPLAIN
ตาม Query ที่เกิด Deadlockจริง
อย่าเพิ่ม Index ทุก Column เพราะ Index เองก็เพิ่ม Write Cost
㉘ UPDATE ต้องเจาะจง Row
หลีกเลี่ยง Query กว้างโดยไม่จำเป็น เช่น:
UPDATE `players`
SET `status` = 'active';
ถ้าตั้งใจแก้ Player คนเดียว
ควรใช้:
UPDATE `players`
SET `status` = ?
WHERE `id` = ?;
พร้อม Key/Index ที่เหมาะกับ Access Pattern
㉙ DELETE จำนวนมากก็เกิด Lock Contention ได้
Transaction ที่ลบ Rows จำนวนมากสามารถถือ Locks มากขึ้น
ตัวอย่าง:
DELETE FROM `logs`
WHERE `created_at` < ?;
บน Table ใหญ่
ไม่ควรให้ Cleanup ใหญ่ทำพร้อม Player Load สูงโดยไม่วิเคราะห์
พิจารณา Maintenance หรือ Batch Strategy ตาม Workload
㉚ SELECT ธรรมดาทำ Deadlock ไหม
ขึ้นกับ Isolation, Query และ Locking Behavior
SELECT อ่านปกติไม่เหมือน Locking Read แต่ Queries เช่น:
SELECT ...
FOR UPDATE
มีวัตถุประสงค์ในการ Lock Rows เพื่อ Update ภายใน Transaction
จึงควรใช้เฉพาะเมื่อ Transaction Logic ต้องการจริง
㉛ SELECT FOR UPDATE ต้องระวัง
ตัวอย่าง:
SELECT Row
FOR UPDATE
↓
ถือ Lock
↓
ทำ Logic นาน
↓
UPDATE
↓
Commit
ถ้า Application ทำงานอื่นนานระหว่างนั้น Lock จะถูกถือไว้นานขึ้น
ควรลด Critical Section ให้สั้น
㉜ Deadlock กับ Upsert เกี่ยวไหม
Upsert:
INSERT ...
ON DUPLICATE KEY UPDATE ...
ยังเป็น Write Operation
ดังนั้นยังสามารถเกี่ยวข้องกับ Locks และ Concurrent Writes
การใช้ Upsert ลด Check-before-write Round Trips ใน Use Case ที่เหมาะสม แต่ไม่ได้ทำให้ Deadlock เป็นไปไม่ได้
㉝ Deadlock กับ Unique Index
เมื่อหลาย Transactions Insert/Update Keys ที่เกี่ยวข้องพร้อมกัน Unique Constraints และ Index Updates ก็เป็นส่วนหนึ่งของ Transactional Work
จึงต้องวิเคราะห์ Deadlock Output จริง ไม่ควรเดาจาก SQL Statement เพียงบรรทัดเดียว
㉞ Deadlock กับ Foreign Key
Foreign Key Operations สามารถเกี่ยวข้องกับการตรวจ Parent/Child Rows ภายใน Transaction
ถ้า Resources Update/Delete Related Rows พร้อมกันควรตรวจ:
Parent
Child
Update Order
Delete Order
ให้สม่ำเสมอ
㉟ SHOW ENGINE INNODB STATUS สำคัญที่สุดอย่างไร
ใช้:
SHOW ENGINE INNODB STATUS;
MariaDB ระบุว่าคำสั่งนี้แสดงข้อมูล InnoDB จำนวนมาก รวมถึง Deadlocks, Buffer Pool และ I/O.
เมื่อเกิด Deadlock ให้ดูส่วน:
LATEST DETECTED DEADLOCK
เพื่อวิเคราะห์เหตุการณ์ล่าสุด
㊱ Deadlock Report บอกอะไร
SHOW ENGINE INNODB STATUS สามารถแสดงข้อมูลเกี่ยวกับ:
Transactions
Statements
Locks ที่ถืออยู่
Locks ที่กำลังรอ
Transaction ที่ถูก Rollback
ทำให้เห็นว่า Transaction ใดชนกันจริง.
นี่มีค่ามากกว่าการอ่านเพียง:
Error 1213
ใน FiveM Console
㊲ ปัญหาของ SHOW ENGINE INNODB STATUS
มันเน้นข้อมูล Deadlock ล่าสุดเป็นหลัก
หาก Deadlock เกิดหลายครั้งในช่วง Production และคุณเปิดดูช้า อาจไม่เห็น Context ทั้งหมดที่ต้องการ
MariaDB จึงมี:
innodb_print_all_deadlocks
สำหรับ Logging Deadlocks เพิ่มเติม.
㊳ innodb_print_all_deadlocks คืออะไร
MariaDB Troubleshooting Documentation ระบุว่า:
innodb_print_all_deadlocks
ปิดอยู่เป็นค่าเริ่มต้น และเมื่อเปิดจะเขียนรายละเอียด Deadlocks ที่ตรวจพบลง MariaDB Error Log.
นี่มีประโยชน์มากกับปัญหา Deadlock ที่เกิดเป็นช่วงๆ
㊴ เปิด innodb_print_all_deadlocks ตอนไหน
เหมาะเมื่อ:
Deadlock เกิดซ้ำ
↓
แต่จับตอนเกิดไม่ทัน
เปิด Logging ชั่วคราวหรือในช่วง Diagnostic ตาม Operations Policy
จากนั้นเก็บ:
Timestamp
Transaction
SQL
Database User
เพื่อเทียบกับ FiveM Logs
㊵ อย่าลืม Log Volume
เมื่อเปิด Diagnostic Logging ควรตรวจ:
Disk Space
Log Rotation
Error Log Size
เพราะระบบที่ Deadlock บ่อยมากอาจสร้าง Log จำนวนมาก
เป้าหมายคือเก็บหลักฐานเพื่อแก้ Root Cause ไม่ใช่เปิดทุก Debug Option โดยไม่มี Monitoring
㊶ วิธีจับ Resource ต้นเหตุ
ใช้สองฝั่งร่วมกัน:
MariaDB
SHOW ENGINE INNODB STATUS
Error Log
Deadlock Report
FiveM / oxmysql
mysql_debug
Resource Query Logs
Server Console
แล้ว Match ด้วย:
เวลาเกิด
+
SQL
+
Table
oxmysql สามารถรายงาน Real Query Speeds ผ่าน Debug UI/Console เมื่อเปิด Debug.
㊷ ตัวอย่างการจับคู่
MariaDB Deadlock Log:
18:02:15
UPDATE player_settings ...
FiveM Console:
18:02:15
resource_a
จากนั้นตรวจ:
resource_a/server.lua
ว่ามี Transaction ลำดับอย่างไร
ถ้าอีก Transaction มาจาก:
resource_b
ก็ต้องเปรียบเทียบ Order ของทั้งสอง Resource
㊸ Deadlock เกิดจาก Resource คนละตัวได้
ตัวอย่าง:
resource_character
↓
UPDATE characters
↓
UPDATE metadata
อีก Resource:
resource_metadata
↓
UPDATE metadata
↓
UPDATE characters
แต่ละ Resource ดูถูกต้องเมื่อดูแยก
ปัญหาเกิดเมื่อรันพร้อมกัน
นี่คือเหตุผลที่ Database Access Convention ควรเป็นมาตรฐานระดับ Server ไม่ใช่ Resource เดียว
㊹ Framework กับ Custom Script อาจชนกัน
Framework อาจ Update:
users
characters
ขณะที่ Custom Script Update Tables เดียวกันด้วย Query ของตัวเอง
ถ้า Custom Script ไม่เข้าใจ Transaction Order ของ Framework ก็สามารถเพิ่ม Deadlock Risk
ก่อนแก้ Framework Code ให้ตรวจ Custom Resources ที่แตะ Table เดียวกันด้วย
㊺ Resource ไหนใช้ Table เดียวกันต้องทำ Inventory
ทำรายการ:
characters
→ framework
→ multicharacter
→ admin
→ autosave
vehicles
→ garage
→ impound
→ admin
จากนั้นตรวจ:
ใคร UPDATE
ใคร DELETE
ใคร Transaction
ช่วยเห็น Conflict Point ได้เร็วขึ้น
㊻ Retry อย่างเดียวไม่พอ
MariaDB Error 1213 แนะนำให้ Restart Transaction แต่ถ้า Architecture สร้าง Deadlock ซ้ำด้วย Pattern เดิม Retry อาจเพียงทำให้บางครั้งผ่าน บางครั้งไม่ผ่าน.
เป้าหมายระยะยาวต้องลด:
Lock Cycle
Transaction Duration
Hot Rows
Inconsistent Order
㊼ Retry + Backoff คืออะไร
แทน Retry ทันทีพร้อมกันทุก Request:
Deadlock
↓
Retry ทุกตัวทันที
↓
ชนกันอีก
สามารถออกแบบ Retry ที่มี Delay เล็กน้อยและจำกัด Attempts
แต่ต้องระวัง FiveM Server Event Flow และไม่ทำให้ Player Action ถูก Execute ซ้ำด้านอื่น
㊽ Retry ต้อง Idempotent เมื่อทำได้
Idempotent หมายถึง Operation ที่ทำซ้ำแล้วไม่สร้างผลซ้ำผิดปกติ
ตัวอย่างง่าย:
UPDATE `player_settings`
SET `theme` = ?
WHERE `identifier` = ?;
มักออกแบบ Retry ง่ายกว่า Operation ที่:
เพิ่ม Counter
ส่ง Reward
สร้าง Record ใหม่หลายจุด
ดังนั้น Retry Strategy ต้องอิง Business Operation จริง
㊾ ไม่ควร Retry ทุก Database Error
แยก:
Deadlock
→ อาจ Retry
Unknown Column
→ Migration Problem
Access Denied
→ Permission Problem
Unknown Database
→ Connection Config
Syntax Error
→ SQL Problem
Retry Unknown column 10 ครั้งก็ไม่ทำให้ Column โผล่มา
ต้องจัด Error Handling ตามชนิด Error
㊿ Transaction Isolation Level เกี่ยวหรือไม่
Isolation Level สามารถมีผลต่อ Transaction Visibility และ Locking Semantics
oxmysql Documentation สำหรับ Transaction มี Configuration เกี่ยวกับ Transaction Isolation Level ด้วย.
แต่ไม่ควรเปลี่ยน Isolation Level เพื่อแก้ Deadlock เป็นขั้นตอนแรก
ให้หา Transactions ที่ชนกันก่อน
51. Deadlock หลังเปลี่ยน Isolation Level
ถ้าปัญหาเริ่มหลัง Configuration Change ให้เปรียบเทียบ:
ก่อนเปลี่ยน
↓
ไม่มี Deadlock
หลังเปลี่ยน
↓
Deadlock เพิ่ม
แต่ยังต้องดู Deadlock Report จริง
อย่า Rollback Configuration จากความสัมพันธ์ทางเวลาเพียงอย่างเดียวโดยไม่มีข้อมูล
52. Deadlock หลังเพิ่ม Index
Index Change สามารถเปลี่ยน Access Path และ Write Behavior ของ Query ได้
หาก Deadlock เริ่มหลัง Migration:
CREATE INDEX
DROP INDEX
ALTER TABLE
ให้ตรวจ Query Plan และ Deadlock Report ใหม่
Migration ผ่านไม่ได้หมายความว่า Runtime Concurrency จะเหมือนเดิม
53. Deadlock หลัง Resource Update
ตรวจ:
Transaction ใหม่หรือไม่
Update Order เปลี่ยนหรือไม่
เพิ่ม Table ใหม่หรือไม่
เพิ่ม SELECT FOR UPDATE หรือไม่
เพิ่ม Autosave หรือไม่
แล้วเปรียบเทียบกับ Version ก่อน Update
54. Deadlock เฉพาะตอน Player เยอะ
นี่บ่งชี้ Concurrency เป็นตัวเร่งปัญหา
เช่น:
20 Players
→ ไม่มีปัญหา
300 Players
→ Deadlock
ไม่จำเป็นต้องหมายความว่า Hardware แย่
อาจเป็น Transaction Pattern ที่โอกาสชนเพิ่มเมื่อ Concurrent Requests สูงขึ้น
55. Deadlock เฉพาะบาง Player
ตรวจว่าผู้เล่นเหล่านั้นใช้ Shared Records หรือ Multi-resource Feature เดียวกันหรือไม่
เช่น:
Character
Vehicle
Settings
ถูกแก้จากหลาย Systems พร้อมกัน
Deadlock มักเกี่ยวกับ Data Access Pattern มากกว่าตัว Player เอง
56. Deadlock กับ Admin Action
Admin Tool ที่แก้ข้อมูลผู้เล่นตรง Database อาจชนกับ Autosave
ตัวอย่าง:
Admin Update Character
พร้อม:
Player Autosave Character
ถ้า Transactions แตะ Tables/Rows หลายชุดคนละ Order ก็สามารถเกิด Deadlock
ควรให้ Admin Operations ใช้ Data Access Pattern ที่สอดคล้องกับ Gameplay Resources
57. Deadlock กับ Scheduled Cleanup
Cron/Resource Cleanup อาจ:
DELETE old rows
UPDATE status
พร้อม Gameplay Writes
ถ้า Job ใหญ่ ควรเลือกช่วง Load ต่ำหรือ Batch งาน
ไม่ควรให้ Maintenance Query ใหญ่ทำงานพร้อม Peak Players โดยไม่ Benchmark
58. Deadlock กับ Bulk Update
ตัวอย่าง:
UPDATE `players`
SET `status` = 'offline'
WHERE `last_seen` < ?;
หากแตะ Rows จำนวนมากใน Transaction เดียว ขณะที่ Players กำลัง Save Rows เดียวกันอยู่ ก็เพิ่ม Lock Contention ได้
พิจารณา Batch และ Maintenance Strategy
59. Connection Pool ใหญ่แก้ Deadlockไหม
ไม่
เพิ่ม Concurrent Connections อาจทำให้ Queries ทำงานพร้อมกันได้มากขึ้น แต่ Deadlock เกิดจาก Lock Dependency ระหว่าง Transactions
ดังนั้น:
Connection Pool
≠
Deadlock Fix
ต้องแก้ Transaction Order และ Critical Section
60. เพิ่ม max_connections แก้ Deadlockไหม
ไม่
max_connections เกี่ยวกับจำนวน Database Connections
Deadlock เกี่ยวกับ:
Transactions
+
Locks
การเพิ่ม Connections ไม่ทำลาย Lock Cycle และอาจเพิ่ม Concurrent Workload ด้วย
61. เพิ่ม innodb_lock_wait_timeout แก้ Deadlockไหม
ไม่ใช่คำตอบหลัก
Deadlock Detector ถูกออกแบบเพื่อค้นหาวงจรและจัดการโดยไม่ต้องรอ Lock Timeout ตามปกติ ขณะที่หากปิด Deadlock Detection MariaDB จะพึ่ง innodb_lock_wait_timeout มากขึ้น.
ดังนั้น Deadlock ควรถูกแก้ที่ Transaction Design
62. ปิด innodb_deadlock_detect ดีไหม
โดยทั่วไปไม่ควรทำเพียงเพื่อให้ Error 1213 หาย
MariaDB ระบุว่า Deadlock Detection เปิดเป็น Default และการปิดอาจมีประโยชน์เฉพาะ Workload Concurrency สูงบางลักษณะที่ Detector เองเป็น Bottleneck แต่จะทำให้ระบบพึ่ง Lock Wait Timeout แทน.
นี่เป็น Advanced Database Tuning ที่ต้อง Benchmark จริง
63. Deadlock Monitoring Checklist
เก็บอย่างน้อย:
วันที่/เวลา
Error 1213 หรือไม่
Resource
Query
Table
Transaction
SHOW ENGINE INNODB STATUSBlocking/Waiting Statements
Transaction ที่ Rollback
Query Execution Time
Player Count ตอนเกิด
Autosave กำลังทำหรือไม่
Cleanup Job กำลังทำหรือไม่
Resource Update ล่าสุด
Database Migration ล่าสุด
64. วิธีแก้ Deadlock แบบเป็นขั้นตอน
① เก็บ Error 1213
② จดเวลา
③ SHOW ENGINE INNODB STATUS
④ เปิด innodb_print_all_deadlocks หากต้องเก็บหลายเหตุการณ์
⑤ หา Transactions ทั้งสองฝั่ง
⑥ หา Resources
⑦ ตรวจ Lock Order
⑧ ลด Transaction Size
⑨ ลด Transaction Duration
⑩ Optimize Query/Index
⑪ ลด Hot Row Writes
⑫ กระจาย Autosave
⑬ เพิ่ม Retry แบบจำกัดถ้าเหมาะ
⑭ Load Test
⑮ Monitor Production
MariaDB แนะนำ SHOW ENGINE INNODB STATUS และ innodb_print_all_deadlocks เป็นเครื่องมือสำคัญในการตรวจ Deadlocks.
65. Checklist Transaction FiveM
ก่อน Production ตรวจว่า:
Transaction จำเป็นจริง
ไม่มี Query ที่ไม่เกี่ยวข้องอยู่ใน Transaction
Transaction สั้น
ไม่มี
Wait()โดยไม่จำเป็นไม่รอ Client
Query Order สม่ำเสมอ
Rows ถูกล็อกใน Order เดียวกัน
WHERE Clause เจาะจง
Index เหมาะสม
ไม่มี Shared Hot Row ที่ไม่จำเป็น
Autosave ไม่ Burst เกินไป
Cleanup ไม่ชน Peak
Retry จำกัดจำนวน
Retry ไม่สร้าง Side Effect ซ้ำ
Deadlock ถูก Log
Load Test Concurrent Writes
ตาราง Deadlock กับปัญหาอื่น
| ปัญหา | ความหมายหลัก |
|---|---|
| Deadlock Error 1213 | Transactions รอกันเป็นวงจร |
| Lock Wait Timeout | รอ Lock นานเกินกำหนด |
| Too many connections | Connection Capacity เต็ม |
wait_timeout | Idle Connection Timeout |
| Slow Query | Query Execution ช้า |
| Access Denied | Authentication/Permission |
| Unknown Column | Schema/Migration |
MariaDB กำหนด Error 1213 โดยเฉพาะสำหรับ Deadlock found when trying to get lock.
FiveM Deadlock Found When Trying to Get Lock แก้อย่างไร
อย่าเริ่มจาก Restart Database
ใช้:
SHOW ENGINE INNODB STATUS;
แล้วตรวจ Deadlock ล่าสุดก่อน เพราะ MariaDB สามารถแสดง Statements, Locks และ Transaction ที่เกี่ยวข้องกับ Deadlock ได้.
จากนั้นหา Resource ที่ Execute SQL เหล่านั้นและแก้ Transaction Order
FiveM Error 1213 คืออะไร
MariaDB Error 1213 คือ:
ER_LOCK_DEADLOCK
พร้อมข้อความ:
Deadlock found when trying to get lock;
try restarting transaction
FiveM Deadlock กับ oxmysql เกี่ยวกันไหม
oxmysql เป็น Database Resource ที่ส่ง Queries/Transactions ไปยัง Database ส่วน Deadlock ถูกตรวจและจัดการใน Database Engine ตาม Transaction/Lock Pattern ที่ Queries สร้าง
oxmysql มี MySQL.transaction สำหรับหลาย Queries ที่ต้อง Commit พร้อมกัน.
ดังนั้นต้องตรวจ Resource SQL/Transaction Design ก่อนกล่าวว่า oxmysql เป็นสาเหตุ
FiveM ดู Deadlock ล่าสุดยังไง
ใช้:
SHOW ENGINE INNODB STATUS;
แล้วหา Deadlock Information
MariaDB ระบุว่าคำสั่งนี้แสดงรายละเอียด Deadlocks, Buffer Pool และ I/O ของ InnoDB.
FiveM ดู Deadlock ทุกครั้งได้ไหม
MariaDB รองรับ:
innodb_print_all_deadlocks
เพื่อเขียนรายละเอียด Deadlocks ที่ตรวจพบลง Error Log และค่านี้ปิดอยู่เป็น Default ตาม Documentation.
FiveM Retry Transaction หลัง Deadlock ได้ไหม
ได้ใน Use Case ที่ออกแบบรองรับ เพราะ Error 1213 เองระบุให้ลอง Restart Transaction.
แต่ต้อง:
จำกัด Attempts
ป้องกัน Side Effect ซ้ำ
Log Failure
และยังต้องแก้ Root Cause หาก Deadlock เกิดบ่อย
FiveM Deadlock แก้ด้วยเพิ่ม Timeout ได้ไหม
ไม่ใช่วิธีหลัก
Deadlock เป็น Lock Cycle ส่วน innodb_lock_wait_timeout เป็นเวลารอ Lock และ MariaDB มี Deadlock Detector แยกต่างหาก.
FiveM Deadlock แก้ด้วยเพิ่ม max_connections ได้ไหม
ไม่ได้ เพราะ max_connections เป็นเรื่อง Connection Capacity ไม่ใช่ Lock Dependency
ต้องแก้ SQL/Transaction Order
FiveM Deadlock เกิดจาก Autosave ได้ไหม
เกิดได้หาก Autosave สร้าง Concurrent Writes ไปยัง Rows/Tables ที่ Resources อื่นกำลัง Update และ Lock Order ขัดกัน
ควรตรวจ Deadlock Report เพื่อยืนยัน ไม่ควรเดาจาก Autosave อย่างเดียว
FiveM Deadlock เกิดจาก Player เยอะไหม
Player เยอะเพิ่ม Concurrent Requests ได้ แต่ Root Cause คือ Transaction/Lock Pattern
Server Player น้อยก็ Deadlock ได้ถ้ามี Transactions สองชุดล็อกข้อมูลสวนลำดับกัน
FiveM Deadlock เกิดจาก Query ช้าไหม
Query ช้าไม่ใช่นิยามของ Deadlock แต่ Transaction ที่ทำงานนานสามารถถือ Locks นานขึ้นและเพิ่มช่วงเวลาที่ Concurrent Transactions จะชนกัน
ใช้ oxmysql Debug Tools ตรวจ Query Timing ร่วมกับ MariaDB Deadlock Report.
FAQ FiveM MariaDB Deadlock
Deadlock คืออะไร
คือ Transactions หลายชุดถือ Locks แล้วต่างฝ่ายต่างรอ Lock ที่อีกฝ่ายถืออยู่จนเกิดวงจร
Error 1213 คืออะไร
MariaDB Error 1213 คือ ER_LOCK_DEADLOCK — Deadlock found when trying to get lock; try restarting transaction.
Deadlock กับ Lock Wait Timeout เหมือนกันไหม
ไม่ Deadlock เป็นวงจรการรอ ส่วน Lock Wait Timeout อาจเป็น Transaction หนึ่งรออีก Transaction อย่างเดียว
MariaDB ตรวจ Deadlock อัตโนมัติไหม
InnoDB Deadlock Detector เปิดเป็น Default ใน MariaDB ตาม Documentation.
ดู Deadlock ยังไง
ใช้:
SHOW ENGINE INNODB STATUS;
ซึ่งแสดง Deadlock Details ของ InnoDB.
เก็บ Log Deadlock ทุกครั้งได้ไหม
ได้ โดย innodb_print_all_deadlocks สามารถเขียน Deadlocks ที่ตรวจพบลง MariaDB Error Log.
Retry Transaction ได้ไหม
ได้เมื่อ Operation ถูกออกแบบให้ Retry ได้ เพราะ Error 1213 แนะนำให้ Restart Transaction.
Retry อย่างเดียวพอไหม
ไม่ ถ้า Deadlock เกิดบ่อยต้องแก้ Lock Order, Transaction Duration และ Query Design
oxmysql Transaction ทำ Deadlock ได้ไหม
SQL ที่ Execute ภายใน Transaction สามารถสร้าง Locks และ Deadlock ได้ตาม Concurrent Access Pattern ส่วน oxmysql มี Transaction API สำหรับ Commit หลาย Queries ร่วมกัน.
Deadlock แก้ด้วย Restart MariaDB ไหม
ไม่ใช่การแก้ Root Cause เพราะ Resource เดิมสามารถสร้าง Deadlock ใหม่หลัง Restart
Deadlock แก้ด้วยเพิ่ม max_connections ไหม
ไม่ เพราะ Deadlock เป็นปัญหา Lock Dependency ไม่ใช่จำนวน Connections
วิธีป้องกัน Deadlock ที่สำคัญที่สุดคืออะไร
ทำ Transactions ให้สั้น ใช้ Lock/Update Order ที่สม่ำเสมอ ลด Hot Rows และตรวจ Deadlock Report จริงก่อนแก้
ประเด็นสำคัญ
เมื่อ FiveM ขึ้น:
Deadlock found when trying to get lock
ให้คิด:
Transaction A
↓
ถือ Lock
Transaction B
↓
ถือ Lock
A ต้องการของ B
B ต้องการของ A
= Deadlock
MariaDB กำหนดปัญหานี้เป็น Error 1213 / ER_LOCK_DEADLOCK และแนะนำให้ Restart Transaction หลัง Deadlock.
แต่การ Retry เป็นเพียง Safety Mechanism หนึ่ง สิ่งที่ต้องทำจริงคือเปิด:
SHOW ENGINE INNODB STATUS;
เพื่อดู SQL, Locks และ Transactions ที่ชนกัน และหากปัญหาเกิดเป็นช่วงๆ สามารถใช้ innodb_print_all_deadlocks เพื่อบันทึก Deadlock Details ลง Error Log.
จากนั้นแก้:
Lock Order
Transaction Size
Transaction Duration
Slow Query
Hot Row
Autosave Burst
Resource Conflict
ก่อนเพิ่ม Timeout หรือเปลี่ยน Database Capacity
สำหรับผู้อ่าน comsiam ให้จำสูตร “Deadlock → หา 2 Transactions ที่ชน → จัด Order ให้เหมือนกัน → ทำ Transaction ให้สั้น” และ comsiam แนะนำให้เก็บ Deadlock Report คู่กับ oxmysql Query Logs ทุกครั้ง เพราะ Error 1213 บอกเพียงว่าเกิด Deadlock แต่ SQL และ Locks ใน InnoDB Report จะบอกว่า Resource ไหนต้องแก้จริง
Comments
Post a Comment