FiveM MariaDB Autocommit คืออะไร? COMMIT, ROLLBACK และ Explicit Transaction ทำงานต่างกันอย่างไร
FiveM MariaDB Autocommit คือพฤติกรรมของฐานข้อมูลที่กำหนดว่า SQL Statement แต่ละคำสั่งจะถูก Commit โดยอัตโนมัติทันทีหลังทำสำเร็จ หรือจะต้องรอให้ Application สั่ง COMMIT เองภายใน Transaction
MariaDB เปิด autocommit เป็นค่าเริ่มต้น โดยเมื่อ autocommit=1 SQL Statement แต่ละคำสั่งจะถูก Commit หลังทำงานสำเร็จ ส่วนเมื่อ autocommit=0 การเปลี่ยนแปลงจะต้องถูกจบด้วย COMMIT หรือยกเลิกด้วย ROLLBACK.
สำหรับ FiveM Developer ที่ใช้ oxmysql เรื่องนี้สำคัญมาก เพราะต้องแยกให้ออกระหว่าง:
Query เดี่ยว
↓
Database จัด Transaction ให้
↓
Commit ตาม Autocommit
กับ
หลาย Queries
↓
MySQL.transaction
↓
สำเร็จทั้งหมด
→ Commit
มี Query ใดล้มเหลว
→ ไม่ Commit ทั้งชุด
oxmysql ระบุว่า MySQL.transaction ใช้ Execute หลาย Queries ภายใน Transaction เดียว และจะ Commit ก็ต่อเมื่อทุก Query สำเร็จ หาก Query ใดล้มเหลวจะไม่มี Queries ในชุดนั้นถูก Commit.
① Autocommit คืออะไร
เมื่อ:
autocommit = 1
SQL Statement แต่ละคำสั่งโดยทั่วไปจะเป็น Transaction ของตัวเอง และเมื่อ Statement สำเร็จ MariaDB จะ Commit ให้โดยอัตโนมัติ.
ตัวอย่าง:
UPDATE `player_settings`
SET `theme` = 'dark'
WHERE `identifier` = 'player_001';
แนวคิดคือ:
START
↓
UPDATE
↓
สำเร็จ
↓
COMMIT อัตโนมัติ
Developer จึงไม่จำเป็นต้องเขียน COMMIT เองสำหรับทุก Query เดี่ยวเมื่อ Connection ทำงานใน Autocommit Mode
② ค่า Default ของ MariaDB คืออะไร
MariaDB ระบุว่า autocommit มีค่า Default เป็นเปิด หรือ:
autocommit = 1
ทำให้ Queries ถูก Commit โดยอัตโนมัติหลังทำงานสำเร็จ.
ตรวจค่าได้ด้วย:
SELECT @@autocommit;
หรือ:
SHOW VARIABLES LIKE 'autocommit';
หากได้:
1
หมายถึง Autocommit เปิด
ถ้าได้:
0
หมายถึง Autocommit ปิดสำหรับ Scope ที่กำลังตรวจ
③ COMMIT คืออะไร
COMMIT ใช้จบ Transaction และทำให้การเปลี่ยนแปลงข้อมูลภายใน Transaction นั้นถูกบันทึกถาวรและสามารถมองเห็นจาก Transactions อื่นตาม Isolation Rules.
ตัวอย่าง:
START TRANSACTION;
UPDATE `player_profiles`
SET `status` = 'active'
WHERE `id` = 10;
COMMIT;
Flow:
START TRANSACTION
↓
UPDATE
↓
COMMIT
↓
ข้อมูลถูกบันทึก
④ ROLLBACK คืออะไร
ROLLBACK ใช้จบ Transaction เช่นกัน แต่ยกเลิกการเปลี่ยนแปลง SQL Data ที่ยังไม่ Commit ทำให้ Changes เหล่านั้นไม่กลายเป็นข้อมูลที่ Transaction อื่นเห็นในภายหลัง.
ตัวอย่าง:
START TRANSACTION;
UPDATE `player_profiles`
SET `status` = 'banned'
WHERE `id` = 10;
ROLLBACK;
หลัง ROLLBACK การเปลี่ยน status ภายใน Transaction นี้จะไม่ถูก Commit
Flow:
START
↓
UPDATE
↓
เกิดปัญหา
↓
ROLLBACK
↓
ยกเลิก Changes
⑤ COMMIT กับ ROLLBACK ต่างกันอย่างไร
COMMIT
Changes
↓
บันทึก
↓
Transaction จบ
ROLLBACK
Changes ที่ยังไม่ Commit
↓
ยกเลิก
↓
Transaction จบ
MariaDB ระบุว่า START TRANSACTION เริ่ม Transaction, COMMIT ทำ Changes ให้ถาวร และ ROLLBACK ยกเลิก Changes ของ Transaction.
⑥ START TRANSACTION คืออะไร
MariaDB รองรับ:
START TRANSACTION;
และ:
BEGIN;
สำหรับเริ่ม Explicit Transaction.
ตัวอย่าง:
START TRANSACTION;
UPDATE `characters`
SET `status` = 'online'
WHERE `id` = 100;
UPDATE `player_settings`
SET `last_login` = NOW()
WHERE `character_id` = 100;
COMMIT;
สอง UPDATE นี้อยู่ภายใน Transaction เดียวกัน
⑦ Explicit Transaction คืออะไร
หมายถึง Developer กำหนด Transaction Boundary อย่างชัดเจน:
START TRANSACTION
↓
SQL
↓
SQL
↓
SQL
↓
COMMIT / ROLLBACK
ตรงข้ามกับ Autocommit ที่ Statement เดี่ยวถูก Commit อัตโนมัติ
Explicit Transaction เหมาะเมื่อหลาย Database Operations ต้องเป็น หน่วยงานเดียวกัน
⑧ ตัวอย่างที่ควรใช้ Transaction
สมมติต้องย้ายข้อมูลคะแนนระหว่าง Profile A และ Profile B
ต้องการ:
A ลด 100
+
B เพิ่ม 100
ห้ามเกิด:
A ลด 100
แต่
B ไม่เพิ่ม
จึงควรอยู่ Transaction เดียวกัน:
START TRANSACTION;
UPDATE `profiles`
SET `points` = `points` - 100
WHERE `id` = 1;
UPDATE `profiles`
SET `points` = `points` + 100
WHERE `id` = 2;
COMMIT;
ถ้า Operation ที่สองล้มเหลว Application ควร Rollback ทั้งชุด
⑨ oxmysql ทำ Transaction อย่างไร
oxmysql มี:
MySQL.transaction.await(...)
สำหรับหลาย Queries ที่ต้อง Commit หรือ Fail พร้อมกัน.
ตัวอย่าง:
local success = MySQL.transaction.await({
{
query = [[
UPDATE `player_profiles`
SET `points` = `points` - ?
WHERE `id` = ?
]],
values = {
100,
sourceId
}
},
{
query = [[
UPDATE `player_profiles`
SET `points` = `points` + ?
WHERE `id` = ?
]],
values = {
100,
targetId
}
}
})
if not success then
print('Transaction failed')
end
oxmysql จะคืน Boolean แสดงผลของ Transaction และ Commit เมื่อ Queries ทั้งหมดสำเร็จ.
⑩ Query เดี่ยวจำเป็นต้องใช้ MySQL.transaction ไหม
ไม่จำเป็นเสมอไป
ตัวอย่าง:
MySQL.update.await(
'UPDATE `player_settings` SET `theme` = ? WHERE `identifier` = ?',
{
'dark',
identifier
}
)
ถ้าเป็น Operation เดี่ยวและไม่มี Database Operation อื่นที่ต้อง Commit/Fail พร้อมกัน การสร้าง Multi-statement Transaction เพิ่มอาจไม่ได้ให้ประโยชน์
ใช้ Transaction เมื่อมี Atomic Requirement จริง
⑪ Atomic คืออะไร
หมายถึง Operation ต้องเกิดแบบ:
ทั้งหมด
หรือ
ไม่เกิดเลย
ตัวอย่าง:
Query A สำเร็จ
Query B สำเร็จ
Query C สำเร็จ
→ COMMIT
แต่ถ้า:
Query A สำเร็จ
Query B พัง
ต้อง:
ROLLBACK
แทนปล่อย A ถูก Commit เพียงตัวเดียว
นี่คือเหตุผลหลักที่ oxmysql มี Transaction API.
⑫ Autocommit ทำให้ Query เดี่ยวปลอดภัยกว่าไหม
Autocommit ทำให้ Statement เดี่ยวถูก Commit โดยอัตโนมัติหากทำงานสำเร็จ แต่ไม่ได้ทำให้ Business Logic หลาย Queries กลายเป็น Atomic Operation
ตัวอย่าง:
MySQL.update.await(queryA)
MySQL.update.await(queryB)
ถ้า queryA สำเร็จและ Commit แล้ว แต่ queryB ล้มเหลว:
A = ถูกบันทึกแล้ว
B = ไม่สำเร็จ
ไม่สามารถหวังว่า Database จะ Rollback A ให้อัตโนมัติ เพียงเพราะสองบรรทัดอยู่ติดกันใน Lua
⑬ นี่คือเหตุผลที่ Transaction สำคัญ
เปรียบเทียบ:
ไม่มี Transaction
Query A
↓
Commit
Query B
↓
Error
ผล
A เปลี่ยนแล้ว
B ไม่เปลี่ยน
มี Transaction
Query A
↓
Query B
↓
Error
↓
Rollback ทั้งชุด
สำหรับข้อมูลที่ต้องสัมพันธ์กัน Transaction จึงสำคัญกว่าเพียงการเรียก Query หลายครั้งตามลำดับ
⑭ ปิด autocommit แล้วเกิดอะไรขึ้น
MariaDB ระบุว่าเมื่อ:
autocommit = 0
Transactions จะไม่ถูก Commit อัตโนมัติแบบ Default และต้องจบด้วย COMMIT หรือ ROLLBACK.
ตัวอย่าง:
SET autocommit = 0;
UPDATE `characters`
SET `status` = 'online'
WHERE `id` = 100;
COMMIT;
แต่สำหรับ FiveM Resource ทั่วไป ไม่ควรปิด Autocommit ทั้ง Session แบบสุ่ม เพียงเพราะต้องการ Transaction
ใช้ Transaction API ที่ Database Layer จัดเตรียมไว้จะควบคุมขอบเขตได้ชัดกว่า
⑮ ทำไมปิด Autocommit ทั้ง Session ต้องระวัง
หาก:
autocommit = 0
แล้ว Developer ลืม:
COMMIT
Transaction อาจอยู่เปิดนานกว่าที่ตั้งใจ
ผลที่อาจตามมา:
Locks อยู่ได้นาน
Transaction ค้าง
Resources อื่นรอ
Lock Wait
Deadlock Risk เพิ่ม
ดังนั้น Transaction Boundary ต้องชัดเจน
⑯ เปิด autocommit จาก 0 กลับเป็น 1 ต้องระวัง
MariaDB ระบุว่าหาก autocommit ถูกเปลี่ยนจาก 0 เป็น 1 Transaction ที่เปิดอยู่จะถูก Commit.
ดังนั้นอย่าใช้:
SET autocommit = 1;
เป็นเพียง Toggle ทดสอบใน Production โดยไม่รู้ว่ามี Transaction เปิดอยู่หรือไม่
⑰ START TRANSACTION มีผลต่อ Transaction เดิมไหม
MariaDB ระบุว่า START TRANSACTION จะทำ Implicit Commit ของ Transaction ที่กำลังเปิดอยู่ก่อนเริ่ม Transaction ใหม่.
ดังนั้นไม่ควรคิดว่า:
START TRANSACTION
ภายใน
START TRANSACTION
จะสร้าง Nested Transactions ตามปกติ
Transaction Architecture ต้องถูกออกแบบให้ชัดเจน
⑱ Nested Transaction คืออะไร
Developer บางคนคาดหวัง:
Transaction A
└── Transaction B
└── Transaction C
แล้วให้แต่ละตัว Commit/Rollback แยกกัน
แต่ MariaDB Transaction Control ไม่ได้ทำงานแบบ Nested Transaction ง่ายๆ ด้วยการเรียก START TRANSACTION ซ้อนกัน เพราะการเริ่ม Transaction ใหม่สามารถ Implicitly Commit Transaction ปัจจุบัน.
หากต้องการ Rollback บางจุดต้องศึกษา SAVEPOINT แยกต่างหาก
⑲ Implicit Commit คืออะไร
Implicit Commit คือ MariaDB Commit Transaction ให้เองเมื่อเจอ SQL Statements บางประเภท แม้ Developer ไม่ได้เขียน:
COMMIT;
MariaDB ระบุว่า Statements หลายกลุ่ม โดยเฉพาะ DDL สามารถทำ Implicit Commit ของ Transaction ปัจจุบันก่อน Execute.
นี่เป็นเรื่องสำคัญมากสำหรับ FiveM Database Migration
⑳ DDL คืออะไร
ตัวอย่าง DDL:
CREATE TABLE ...
ALTER TABLE ...
DROP TABLE ...
CREATE INDEX ...
Statements ประเภทนี้เกี่ยวกับ Database Schema
MariaDB ระบุว่า DDL หลายคำสั่งทำ Implicit Commit.
ดังนั้นอย่าคิดว่า:
START TRANSACTION;
ALTER TABLE ...;
ROLLBACK;
จะสามารถย้อน Schema Change ทุกอย่างได้เหมือน UPDATE ธรรมดา
㉑ Migration SQL กับ Transaction ต้องระวัง
สมมติ Migration:
START TRANSACTION;
UPDATE `characters`
SET `status` = 'active';
ALTER TABLE `characters`
ADD COLUMN `last_seen` DATETIME;
ROLLBACK;
ถ้า Developer คาดหวังว่า ROLLBACK จะคืนทุกอย่างกลับเหมือนเดิม อาจผิดจาก Behavior ของ DDL/Implicit Commit
MariaDB ระบุชัดว่า SQL Statements บางประเภทก่อให้เกิด Implicit Commit.
ดังนั้น Migration ต้องมี Backup ไม่ใช่หวังพึ่ง Transaction อย่างเดียว
㉒ Transaction ไม่ใช่ Backup
Transaction สามารถช่วย:
ยกเลิก Changes
ก่อน Commit
แต่ Backup ช่วย:
กู้ข้อมูล
หลังเกิดความเสียหาย
ถ้า:
DROP TABLE
หรือ Migration ถูก Commit ไปแล้ว Transaction เดิมไม่ใช่ Recovery Plan
Database Backup และ Transaction จึงเป็นคนละ Layer
㉓ COMMIT แล้ว ROLLBACK ได้ไหม
เมื่อ Transaction Commit แล้ว Changes นั้นกลายเป็นส่วนหนึ่งของ Database State
การเรียก ROLLBACK ภายหลังไม่ใช่การย้อน Commit เก่าตามใจ
MariaDB ระบุว่า COMMIT จบ Transactionและบันทึก Changes ส่วน ROLLBACK ใช้กับ Transaction ปัจจุบันที่ยังไม่ Commit.
ถ้าต้องย้อนข้อมูลหลัง Commit ต้อง:
Execute Reverse Operation
หรือ
Restore Backup
ตามสถานการณ์
㉔ Resource Error หลัง Query A Commit แล้ว
ตัวอย่าง:
local a = MySQL.update.await(...)
local result = riskyFunction()
local b = MySQL.update.await(...)
ถ้า Query A Commit แล้ว:
riskyFunction()
เกิด Error
Database ไม่รู้ว่า Developer ตั้งใจให้ Query B เกิดคู่กัน
ถ้า A และ B ต้อง Atomic ควรรวม Database Operations ที่เกี่ยวข้องใน Transaction
㉕ Transaction ควรรวม Lua Logic ทั้งหมดไหม
ไม่
Transaction ควรสั้นและเน้น Database Operations ที่ต้อง Atomic
หลีกเลี่ยง:
เริ่ม Transaction
↓
Query
↓
ทำ Lua Loop ยาว
↓
เรียก Network
↓
Wait()
↓
Query อีกครั้ง
↓
Commit
เพราะ Transaction ที่เปิดนานสามารถถือ Locks นานขึ้นและเพิ่ม Lock Contention
㉖ เตรียมข้อมูลก่อนเข้า Transaction
แนวทางที่ดีกว่า:
Validate Player
↓
เตรียม Values
↓
ตรวจ Business Rules ที่ไม่ต้อง Lock
↓
เริ่ม Transaction
↓
SQL ที่จำเป็น
↓
Commit
ทำ Critical Database Section ให้สั้นที่สุดเท่าที่เหมาะสม
㉗ อย่ารอ Client ระหว่าง Transaction
ตัวอย่างที่เสี่ยง:
เริ่ม Transaction
↓
UPDATE
↓
TriggerClientEvent
↓
รอ Player ตอบ
↓
UPDATE
↓
COMMIT
Client อาจ:
Lag
Timeout
Disconnect
และ Transaction ถูกเปิดนานโดยไม่จำเป็น
รวบรวมข้อมูลที่ต้องการก่อนเริ่ม Transaction เมื่อทำได้
㉘ Transaction กับ Lock Wait เกี่ยวกันอย่างไร
Transaction ที่ทำ Writes สามารถถือ InnoDB Locks จน Transaction จบ
ถ้า Transaction A ถือ Row ที่ Transaction B ต้องการ:
A
→ Lock
B
→ Wait
ยิ่ง A อยู่ได้นาน B ก็อาจรอนานขึ้น
ดังนั้น Transaction Design เชื่อมโยงกับปัญหา Lock wait timeout exceeded
㉙ Transaction กับ Deadlock เกี่ยวกันอย่างไร
ตัวอย่าง:
Transaction A
Update Row 1
→ Update Row 2
Transaction B
Update Row 2
→ Update Row 1
อาจเกิด:
A รอ B
B รอ A
เป็น Deadlock
ดังนั้น Transaction ที่ Atomic ถูกต้องยังสามารถ Deadlock ได้ หาก Lock Order ไม่ถูกออกแบบอย่างสม่ำเสมอ
㉚ ใช้ Order เดียวกัน
ถ้าต้องแก้ Player หลายคน:
Player 50
Player 100
ควรให้ทุก Transaction ใช้ Order:
50
↓
100
ไม่ใช่ Transaction หนึ่ง:
50 → 100
อีก Transaction:
100 → 50
ช่วยลดโอกาสเกิด Lock Cycle
㉛ Autocommit ลด Deadlock ได้ไหม
ไม่สามารถตอบแบบตรงๆ ว่าเปิด Autocommit แล้ว Deadlock จะหาย
Statement เดี่ยวที่ Commit เร็วสามารถมี Lock Duration สั้นกว่า Long Transaction ในบาง Workload แต่ Business Operation ที่ต้อง Atomic ยังต้องใช้ Transaction
อย่าแตก Transaction ที่จำเป็นออกเป็น Query เดี่ยวเพียงเพื่อหลีกเลี่ยง Deadlock เพราะอาจสร้าง Data Consistency Problem แทน
㉜ Transaction ใหญ่เกินไปควรแบ่งไหม
พิจารณาว่า Queries ใด จำเป็นต้อง Atomic จริง
ถ้ามี:
Query A
Query B
Query C
Query D
Query E
แต่จริงๆ:
A + B
ต้อง Atomic
C
เป็น Logging
D + E
ทำภายหลังได้
อาจไม่จำเป็นต้องรวมทั้ง 5 Queries ใน Transaction เดียว
ลด Scope ช่วยลดเวลาถือ Locks
㉝ Logging ควรอยู่ Transaction หลักไหม
ขึ้นกับ Business Requirement
ถ้า Log เป็นเพียง:
Diagnostic Log
และไม่จำเป็นต้อง Commit พร้อม Gameplay State อาจไม่ควรทำให้ Transaction หลักยาวขึ้น
แต่ถ้าเป็น Audit Record ที่ต้องเกิดพร้อม Operation จริง ก็อาจต้องรวม
ตัดสินจาก Requirement ไม่ใช่ใช้สูตรเดียวกับทุก Table
㉞ Transaction กับ Slow Query
ถ้า Query หนึ่งภายใน Transactionใช้เวลานาน:
Transaction เปิด
↓
Query ช้า
↓
Locks อาจอยู่ได้นาน
↓
Transaction อื่นรอ
oxmysql ระบุว่าความเร็ว Query จริงสามารถตรวจผ่าน Debug UI หรือ Server Console เมื่อเปิด mysql_debug และความเร็วขึ้นกับ Hardware, Database Settings, Version และ Current Workload.
จึงควร Optimize Slow Query ก่อนเพิ่ม Transaction Timeout แบบสุ่ม
㉟ mysql_debug ช่วยตรวจ Transaction ได้ไหม
ใช้ตรวจ Queries และ Query Timing ที่ Resource ส่งได้
ตัวอย่าง:
set mysql_debug true
แล้วดูว่า Transaction มี:
Query ไหนช้า
Query ไหนถูกเรียกซ้ำ
Resource ไหนเป็นต้นเหตุ
oxmysql ระบุว่า Real Query Speeds จะรายงานผ่าน Debug UI และ Server Console เมื่อเปิด Debug.
㊱ Transaction กับ MySQL.prepare ต่างกัน
MySQL.prepare ใช้สำหรับ Query ที่ถูกเรียกบ่อยและรองรับ Parameter Sets ตาม oxmysql Documentation.
ส่วน:
MySQL.transaction
ใช้กำหนด Atomic Boundary ของหลาย Queries.
ดังนั้น:
Prepare
≠
Transaction
㊲ Transaction กับ rawExecute ต่างกัน
rawExecute เป็น API สำหรับ Execute Query ในรูปแบบที่ oxmysql รองรับ และรองรับ Parameter Sets หลายชุด ขณะที่ Transaction มีหน้าที่ Commit หลาย Queries เป็นชุดเดียว.
อย่าสับสน Performance API กับ Transaction Semantics
㊳ Transaction กับ Isolation Level
จากบทความก่อนหน้า:
Transaction
กำหนด:
อะไรอยู่ในหน่วย Commit/Rollback เดียว
ส่วน:
Isolation Level
กำหนด:
Transaction เห็นข้อมูลของ Transaction อื่นอย่างไร
เป็นคนละเรื่อง แต่ทำงานร่วมกัน
㊴ Autocommit กับ Isolation Level
แม้ autocommit=1 Statement ยังทำงานภายใน Transaction Context ของ Database
MariaDB ระบุว่าเมื่อ Autocommit เปิด แต่ละ SQL Statementจะถูก Commit อัตโนมัติหลังทำงานสำเร็จ.
Isolation Level ยังมีความหมายต่อ Statement/Transaction Behavior ตาม Operation ที่เกิดขึ้น
㊵ SERIALIZABLE กับ Autocommit
MariaDB ระบุว่าภายใต้ SERIALIZABLE เมื่อ Autocommit ถูกปิด Plain SELECT จะถูกเปลี่ยนเป็น Locking Read แต่ถ้า Autocommit เปิด SELECT จะเป็น Transaction ของตัวเองและสามารถเป็น Consistent Read ได้โดยไม่จำเป็นต้อง Block แบบเดียวกัน.
นี่เป็นตัวอย่างที่ชัดว่า:
Isolation Level
+
Autocommit
สามารถมีผลร่วมกันต่อ Locking Behavior
㊶ SAVEPOINT คืออะไร
เมื่อ Transaction ใหญ่จำเป็นจริง Developer อาจต้องการจุด Rollback ภายใน Transaction แทนยกเลิกทั้งหมด
MariaDB มี Transaction Control ที่รองรับ Savepoint ในระบบ Transaction
แต่ FiveM Resource ควรหลีกเลี่ยง Transaction Complexity ที่สูงเกินความจำเป็น ถ้า Business Logic สามารถออกแบบให้เล็กและชัดกว่าได้
㊷ Implicit Commit ที่ควรรู้
MariaDB ระบุว่ามี SQL Statements จำนวนหนึ่งที่ทำ Implicit Commit และหลักทั่วไปคือ DDL Statements มักอยู่ในกลุ่มนี้.
ตัวอย่างที่ควรระวัง:
CREATE
ALTER
DROP
ดังนั้น Gameplay Transaction กับ Database Migration ควรถูกแยก Concept ออกจากกัน
㊸ LOCK TABLES ต้องระวัง
MariaDB ระบุว่า LOCK TABLES จะ Implicitly Commit Active Transaction และการเริ่ม Transaction ใหม่ก็จะ Release Table Locks ที่ได้จาก LOCK TABLES ตาม Behavior ที่กำหนด.
FiveM Resource ทั่วไปไม่ควรนำ LOCK TABLES มาแก้ Concurrency Problem แบบสุ่ม
ใช้ InnoDB Transactions และ Row-level Data Design ที่เหมาะสมก่อน
㊹ อย่าใช้ LOCK TABLES เพื่อแก้ Deadlock แบบง่ายๆ
ถึงการล็อกกว้างขึ้นอาจทำให้ Concurrency ถูก Serialize แต่นั่นอาจสร้าง:
Player A รอ
Player B รอ
Player C รอ
จำนวนมาก
และลด Database Concurrency อย่างหนัก
ควรแก้:
Lock Order
Hot Rows
Transaction Duration
Indexes
ก่อน
㊺ Autocommit กับ INSERT
Query:
INSERT INTO `player_settings`
(`identifier`, `theme`)
VALUES
(?, ?);
เมื่อทำงานเป็น Statement เดี่ยวใน Autocommit Mode จะถูก Commit หลัง Statement สำเร็จตาม MariaDB Autocommit Behavior.
oxmysql MySQL.insert จะคืน Insert ID หากมีค่าที่ใช้ได้.
㊻ Autocommit กับ UPDATE
เช่น:
local affectedRows = MySQL.update.await(
'UPDATE `player_settings` SET `theme` = ? WHERE `identifier` = ?',
{
'dark',
identifier
}
)
oxmysql MySQL.update คืนจำนวน Rows ที่ได้รับผลจาก Query.
ถ้าเป็น Statement เดี่ยวภายใต้ Autocommit Mode Database จะจัดการ Commit ของ Statement ตามปกติ
㊼ SELECT ต้อง Commit ไหม
SELECT ที่อ่านข้อมูลไม่ได้สร้าง Persistent Data Change แบบ UPDATE/INSERT
แต่ MariaDB ยังมอง SQL Access ผ่าน Transaction Semantics และเมื่อ Autocommit เปิด SELECT สามารถเป็น Transaction ของตัวเองได้ในบริบทที่ Documentation กล่าวถึง.
ดังนั้นคำว่า Transaction ไม่ได้หมายถึงเฉพาะ Query ที่เขียนข้อมูลเท่านั้น
㊽ Autocommit ปิดแล้วลืม COMMIT เกิดอะไร
MariaDB ระบุว่าเมื่อ Autocommit ปิด Changes ต้องถูก Commit อย่างชัดเจน และถ้า Transaction ไม่ถูก Commit ก็สามารถถูก Rollback แทนตาม Lifecycle ของ Connection/Transaction.
ใน Application จริงสิ่งที่น่ากังวลเพิ่มเติมคือ Transaction เปิดนานและถือ Locks
จึงควรให้ Transaction Lifecycle สั้นและชัดเจน
㊾ Resource Stop ระหว่าง Transaction
ถ้า Resource หรือ Connection ถูกตัดระหว่าง Transaction ที่ยังไม่ Commit ไม่ควรออกแบบ Business Logic โดยหวังว่า Statements ก่อนหน้าจะถูกบันทึกแน่นอน
หลักสำคัญคือ:
สำเร็จ
→ COMMIT
ล้มเหลว
→ ROLLBACK
และ Application State นอก Database ต้องรับมือ Failure ให้สอดคล้อง
㊿ FiveM Server Crash ระหว่าง Transaction
Transaction Database ถูกออกแบบมาเพื่อรักษา Atomicity ของ Transactional Operations แต่ Server Owner ไม่ควรใช้ Transaction แทน Backup หรือ Crash Recovery Strategy
ระบบ Production ยังต้องมี:
Database Backup
Recovery Plan
Resource Error Handling
แยก
51. Transaction Failure ต้องแจ้ง Player ยังไง
สมมติ Operation Database ไม่ Commit:
Player กด Save
↓
Transaction Failed
Server Logic ควร:
ไม่บอกว่าสำเร็จ
ไม่อัปเดต Cache เป็นค่าที่ผิด
Log Error
Retry เฉพาะกรณีที่เหมาะ
อย่า:
เปลี่ยน Gameplay State ก่อน
↓
Database Fail
↓
แต่ Player เห็นว่าทำสำเร็จ
เพราะ Runtime กับ Persistent State จะไม่ตรงกัน
52. Database Commit ก่อน Client Notification
Pattern ที่ควรพิจารณา:
Validate
↓
Database Transaction
↓
COMMIT สำเร็จ
↓
Update Runtime State
↓
Notify Client
หรือออกแบบ State Synchronization ตาม Resource Architecture
จุดสำคัญคืออย่าบอก Client ว่า Operation สำเร็จก่อนรู้ว่า Database Operation สำคัญ Commit สำเร็จจริง
53. Cache กับ Transaction
ถ้า Resource มี Cache:
Database
+
Memory Cache
ต้องกำหนด Order ให้ชัด
ตัวอย่าง:
Transaction Commit
↓
Update Cache
หรือออกแบบ Consistency Pattern ที่เหมาะสม
ถ้า Update Cache ก่อนแล้ว Transaction Rollback:
Cache = ค่าใหม่
Database = ค่าเก่า
จะเกิด State Divergence
54. Transaction Retry ต้องระวัง
Deadlock Error บางกรณีสามารถ Retry Transaction ได้ แต่ Retry ต้อง:
จำกัดจำนวนครั้ง
ไม่ทำ Side Effect ซ้ำ
ไม่วนไม่สิ้นสุด
และควรแก้ Transaction Order หาก Deadlock เกิดบ่อย
อย่า Retry SQL Syntax Error หรือ Unknown Column ซ้ำๆ เพราะปัญหาเหล่านั้นไม่ได้หายจากการลองใหม่
55. Transaction กับ Network Event
อย่านำ Player-controlled Input ไป Query Databaseโดยไม่ Validate
Flow ที่เหมาะกว่า:
Client
↓
Server Event
↓
Validate
↓
Transaction
↓
Commit
Transaction ช่วยเรื่อง Database Atomicity แต่ไม่ได้ช่วยเรื่อง Server-side Authorization
56. Autocommit ไม่ใช่ Security Feature
autocommit ไม่ได้ป้องกัน:
SQL Injection
Permission Error
Unauthorized Event
Malicious Input
เป็นเพียง Transaction Mode
Security ยังต้องพึ่ง:
Parameterization
Server Validation
Database Permissions
Least Privilege
แยกต่างหาก
57. Autocommit ไม่ได้แก้ Slow Query
ถ้า Query:
SELECT ...
ใช้เวลานานเพราะ Missing Index
การเปลี่ยน:
autocommit 1
→ 0
ไม่ใช่วิธี Optimize Query
ใช้:
EXPLAIN
Index
Query Design
oxmysql Debug
แทน
58. Autocommit ไม่ได้แก้ Too many connections
Too many connections เป็นปัญหา Connection Capacity/Workload
Autocommit เป็น Transaction Commit Behavior
แม้ Long Transactions สามารถทำให้ Workload ค้างนานขึ้น แต่ไม่ควรเปลี่ยน Autocommit เพื่อแก้ Connection Limit โดยไม่วิเคราะห์
59. Autocommit ไม่ได้แก้ Lock Wait
Lock Wait ต้องหา:
Blocking Transaction
แล้วลด:
Transaction Duration
Lock Scope
Query Time
การเปิด/ปิด Autocommit แบบสุ่มอาจเปลี่ยน Transaction Boundary และทำปัญหาซับซ้อนกว่าเดิม
60. Checklist FiveM Autocommit และ Transaction
ก่อนออกแบบ Resource ตรวจ:
Operation มี Query กี่ตัว
Queries ต้องสำเร็จพร้อมกันหรือไม่
ถ้า Query ที่สองพัง Query แรก Commit ได้หรือไม่
ถ้าไม่ได้ ต้องใช้ Transaction
Transaction สั้นหรือไม่
ไม่มี
Wait()โดยไม่จำเป็นไม่รอ Client
ไม่มี External Network Call ระหว่าง Transaction
Query Order สม่ำเสมอ
มี Hot Row หรือไม่
Index เหมาะหรือไม่
Transaction Isolation Level คืออะไร
มี Deadlock หรือไม่
มี Lock Wait หรือไม่
มี Slow Query หรือไม่
DDL ปนใน Transaction หรือไม่
มี Implicit Commit Statement หรือไม่
Resource Error Handling ถูกหรือไม่
Cache Update หลัง Commit ถูกหรือไม่
Client Notification หลัง Success หรือไม่
Retry ปลอดภัยหรือไม่
Side Effects ซ้ำได้หรือไม่
Database User มีสิทธิ์เท่าที่จำเป็น
Backup มีหรือไม่
Migration แยกจาก Gameplay Transaction หรือไม่
mysql_debug พร้อมใช้ตอนวิเคราะห์หรือไม่
Log Transaction Failure หรือไม่
Test Concurrent Requests แล้วหรือไม่
Test Resource Restart แล้วหรือไม่
Test Failure Case แล้วหรือไม่
ตาราง Autocommit, COMMIT และ ROLLBACK
| คำสั่ง/โหมด | หน้าที่ |
|---|---|
autocommit=1 | Commit Statement โดยอัตโนมัติ |
autocommit=0 | ต้อง Commit/Rollback เอง |
START TRANSACTION | เริ่ม Explicit Transaction |
COMMIT | บันทึก Changes และจบ Transaction |
ROLLBACK | ยกเลิก Uncommitted Changes |
MySQL.transaction | ให้ oxmysql Execute หลาย Queries แบบ Commit/Fail เป็นชุด |
MariaDB อธิบาย Transaction Controls เหล่านี้ผ่าน START TRANSACTION, COMMIT, ROLLBACK และ autocommit โดยตรง ขณะที่ oxmysql มี Transaction API สำหรับ FiveM Resources.
FiveM MariaDB autocommit คืออะไร
เมื่อ:
autocommit = 1
MariaDB จะ Commit SQL Statements โดยอัตโนมัติหลัง Statement สำเร็จ และเป็นค่า Default ของ Server Variable นี้.
FiveM ต้องปิด autocommit ไหม
โดยทั่วไปไม่ควรปิดทั้ง Session เพียงเพราะต้องการทำหลาย Queries พร้อมกัน
ถ้าหลาย Queries ต้อง Atomic ให้ใช้ Transaction ที่มีขอบเขตชัดเจน เช่น MySQL.transaction ของ oxmysql.
FiveM COMMIT คืออะไร
ใช้ทำ Transaction Changes ให้ถาวรและจบ Transaction.
FiveM ROLLBACK คืออะไร
ใช้ยกเลิก Uncommitted Changes ของ Transaction ปัจจุบัน.
FiveM Query สองตัวต้องใช้ Transaction ไหม
ถ้าต้องเกิดพร้อมกัน:
A ต้องสำเร็จ
+
B ต้องสำเร็จ
ควรใช้ Transaction
ถ้าสอง Operations เป็นอิสระต่อกัน ไม่จำเป็นต้องรวมเพียงเพราะมีสอง Queries
FiveM MySQL.transaction ใช้ทำอะไร
oxmysql ระบุว่า Transaction Execute หลาย Queries และ Commit เมื่อทุก Query สำเร็จ หากหนึ่ง Query ล้มเหลวจะไม่ Commit Queries ในชุด.
FiveM Transaction ทำให้ Database ช้าหรือไม่
Transaction ไม่ได้ทำให้ Database ช้าโดยอัตโนมัติ แต่ Transaction ที่ใหญ่หรือเปิดนานสามารถเพิ่มช่วงเวลาถือ Locks และสร้าง Concurrency Pressure ได้
ควรตรวจ Query Timing จริงผ่าน oxmysql Debug Tools.
FiveM Transaction ทำให้ Deadlock ได้ไหม
ได้หาก Concurrent Transactions ถือ Locks และต้องการ Locks ของอีกฝ่ายในลำดับที่ทำให้เกิดวงจร
ควรจัด Lock/Update Order ให้สม่ำเสมอ และทำ Transactions ให้สั้น
FiveM Transaction ทำให้ Lock Wait ได้ไหม
ได้ หาก Transaction หนึ่งถือ Lock บน Row ที่อีก Transaction ต้องการ
ต้องหา Blocking Transaction ไม่ใช่เพิ่ม Timeout อย่างเดียว
FiveM Migration ใช้ Transaction ครอบทั้งหมดได้ไหม
ต้องระวังอย่างมาก เพราะ MariaDB ระบุว่า SQL Statements หลายชนิด โดยเฉพาะ DDL สามารถทำ Implicit Commit.
ดังนั้น Backup ยังคงจำเป็นก่อน Migration
FiveM ALTER TABLE แล้ว ROLLBACK ได้ไหม
ไม่ควรออกแบบ Recovery โดยหวังว่า DDL ทุกคำสั่งจะ Rollback ได้เหมือน UPDATE เพราะ MariaDB ระบุว่า DDL หลายคำสั่งทำ Implicit Commit.
ใช้ Backup และ Migration Plan ที่ถูกต้อง
FAQ FiveM MariaDB Autocommit
Autocommit คืออะไร
เป็นโหมดที่กำหนดว่า SQL Statement จะถูก Commit อัตโนมัติหรือรอการ COMMIT เอง โดย MariaDB เปิด Autocommit เป็น Default.
autocommit=1 หมายถึงอะไร
Queries ถูก Commit โดยอัตโนมัติหลัง Statement ทำงานสำเร็จ.
autocommit=0 หมายถึงอะไร
Transactions ต้องถูกจบด้วย COMMIT หรือ ROLLBACK เองแทนการ Commit Statement อัตโนมัติ.
COMMIT คืออะไร
จบ Transaction และบันทึกการเปลี่ยนแปลงให้ถาวร.
ROLLBACK คืออะไร
ยกเลิก Changes ที่ยังไม่ Commit และจบ Transaction.
START TRANSACTION คืออะไร
ใช้เริ่ม Explicit Transaction และ MariaDB รองรับทั้ง START TRANSACTION และ BEGIN.
FiveM ใช้ MySQL.transaction เมื่อไร
ใช้เมื่อหลาย Queries ต้อง Commit พร้อมกันทั้งหมด หรือ Fail พร้อมกันทั้งหมด.
Query เดี่ยวต้องใช้ Transaction ไหม
ไม่จำเป็นเสมอไป หากไม่มี Operation อื่นที่ต้อง Atomic ร่วมกัน
Transaction กับ Autocommit เหมือนกันไหม
ไม่ Autocommit เป็นโหมด Commit Statement ส่วน Transaction คือขอบเขตที่หลาย Operations สามารถ Commit/Rollback ร่วมกัน
เปลี่ยน autocommit จาก 0 เป็น 1 มีผลอะไร
MariaDB ระบุว่าจะ Commit Transaction ที่เปิดอยู่.
DDL ทำ Implicit Commit ได้ไหม
ได้ MariaDB ระบุว่า SQL Statements หลายกลุ่ม โดยเฉพาะ DDL ทำ Implicit Commit.
Transaction ใช้แทน Backup ได้ไหม
ไม่ได้ Transaction ช่วยควบคุม Changes ก่อน Commit ส่วน Backup ใช้สำหรับ Recovery หลังข้อมูลหรือ Schema ได้รับความเสียหาย
ประเด็นสำคัญ
FiveM Developer ควรแยก 3 เรื่องนี้ให้ออก:
Autocommit
→ Statement Commit อัตโนมัติ
Transaction
→ หลาย Operations เป็นหน่วยเดียวกัน
COMMIT / ROLLBACK
→ เลือกบันทึกหรือยกเลิก Transaction
MariaDB เปิด autocommit เป็น Default ดังนั้น Statement เดี่ยวจะถูก Commit อัตโนมัติเมื่อสำเร็จ แต่ถ้า FiveM Resource ต้องให้หลาย Queries สำเร็จหรือผิดพลาดพร้อมกัน ควรใช้ Transaction แทนการยิง Queries แยกทีละคำสั่ง.
ตัวอย่างที่ควรจำ:
Query A สำเร็จ
Query B สำเร็จ
→ COMMIT
Query A สำเร็จ
Query B พัง
→ ROLLBACK
และต้องระวัง Database Migration เพราะ MariaDB ระบุว่า DDL หลายคำสั่งสามารถทำ Implicit Commit ดังนั้นการครอบ ALTER TABLE หรือ CREATE TABLE ด้วย Transaction ไม่ได้หมายความว่าจะสามารถย้อนทุกอย่างด้วย ROLLBACK ได้เสมอ.
สำหรับผู้อ่าน comsiam ให้จำสูตร “Query เดี่ยวใช้ Autocommit ได้ แต่ข้อมูลหลายส่วนที่ต้องไปด้วยกันให้ใช้ Transaction” และ comsiam แนะนำให้ทำ Transaction ให้สั้นที่สุดเท่าที่ Business Logic อนุญาต เพราะ Transaction ที่ถูกต้องไม่ใช่ Transaction ที่ใส่ SQL เยอะที่สุด แต่คือ Transaction ที่ครอบเฉพาะข้อมูลที่ต้อง Commit หรือ Rollback พร้อมกันจริง
Comments
Post a Comment