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

เก็บอย่างน้อย:

  1. วันที่/เวลา

  2. Error 1213 หรือไม่

  3. Resource

  4. Query

  5. Table

  6. Transaction

  7. SHOW ENGINE INNODB STATUS

  8. Blocking/Waiting Statements

  9. Transaction ที่ Rollback

  10. Query Execution Time

  11. Player Count ตอนเกิด

  12. Autosave กำลังทำหรือไม่

  13. Cleanup Job กำลังทำหรือไม่

  14. Resource Update ล่าสุด

  15. 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 ตรวจว่า:

  1. Transaction จำเป็นจริง

  2. ไม่มี Query ที่ไม่เกี่ยวข้องอยู่ใน Transaction

  3. Transaction สั้น

  4. ไม่มี Wait() โดยไม่จำเป็น

  5. ไม่รอ Client

  6. Query Order สม่ำเสมอ

  7. Rows ถูกล็อกใน Order เดียวกัน

  8. WHERE Clause เจาะจง

  9. Index เหมาะสม

  10. ไม่มี Shared Hot Row ที่ไม่จำเป็น

  11. Autosave ไม่ Burst เกินไป

  12. Cleanup ไม่ชน Peak

  13. Retry จำกัดจำนวน

  14. Retry ไม่สร้าง Side Effect ซ้ำ

  15. Deadlock ถูก Log

  16. Load Test Concurrent Writes

ตาราง Deadlock กับปัญหาอื่น

ปัญหาความหมายหลัก
Deadlock Error 1213Transactions รอกันเป็นวงจร
Lock Wait Timeoutรอ Lock นานเกินกำหนด
Too many connectionsConnection Capacity เต็ม
wait_timeoutIdle Connection Timeout
Slow QueryQuery Execution ช้า
Access DeniedAuthentication/Permission
Unknown ColumnSchema/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

Popular posts from this blog

FiveM ยังน่าเล่นไหม? Enhanced เปลี่ยน FiveM แค่ไหน

FiveM คืออะไร เล่นอย่างไร สำหรับมือใหม่ เริ่มต้นตั้งแต่ศูนย์

วิธีตั้ง Admin Permission ด้วย add_ace และ add_principal FiveM แบบละเอียด