FiveM MariaDB Duplicate Entry แก้อย่างไร? วิธีแก้ Error 1062 และตรวจ PRIMARY KEY / UNIQUE KEY ที่ข้อมูลซ้ำ
FiveM MariaDB Duplicate entry คือ Error ที่เกิดเมื่อ Resource พยายาม INSERT หรือเปลี่ยนข้อมูลให้มีค่าซ้ำใน Key ที่ Database กำหนดให้ต้องไม่ซ้ำ เช่น PRIMARY KEY หรือ UNIQUE KEY โดย MariaDB ใช้ Error Code 1062, SQLSTATE 23000 และชื่อ Error ER_DUP_ENTRY.
ตัวอย่าง Error ที่พบบ่อย:
ERROR 1062 (23000):
Duplicate entry '123' for key 'PRIMARY'
หรือ:
Duplicate entry 'license:abc123' for key 'identifier'
สำหรับ FiveM ปัญหานี้มักเกิดหลัง:
สร้าง Character ซ้ำ
Insert Player ซ้ำ
Resource ทำ INSERT ทุกครั้งที่ Join
Migration หรือ Restore ข้อมูลซ้ำ
AUTO_INCREMENT ผิด
Unique Identifier ถูกใช้ซ้ำ
Script Update เปลี่ยน Data Model
Resource สองตัวสร้างข้อมูลเดียวกันพร้อมกัน
สิ่งสำคัญคือ อย่ารีบลบ UNIQUE KEY เพื่อให้ Error หาย เพราะ Constraint เหล่านี้มีหน้าที่รักษาความเป็นเอกลักษณ์ของข้อมูล และ Error 1062 มักกำลังบอกว่ามีปัญหาที่ Application Logic หรือข้อมูลจริงที่ควรแก้ก่อน.
① Error 1062 คืออะไร
MariaDB กำหนด Error:
1062
23000
ER_DUP_ENTRY
เมื่อ Key ที่กำหนดให้ต้อง Unique ได้รับค่าที่มีอยู่แล้ว.
ตัวอย่าง:
CREATE TABLE `characters` (
`id` INT NOT NULL,
`name` VARCHAR(100),
PRIMARY KEY (`id`)
);
มีข้อมูล:
id = 100
แล้ว Resource ทำ:
INSERT INTO `characters`
(`id`, `name`)
VALUES
(100, 'Player Two');
MariaDB จะปฏิเสธเพราะ:
PRIMARY KEY id=100
มีอยู่แล้ว
② PRIMARY KEY คืออะไร
PRIMARY KEY ใช้ระบุ Row แต่ละ Row อย่างไม่ซ้ำ และค่าของ Primary Key ต้อง Unique และไม่เป็น NULL.
ตัวอย่าง:
PRIMARY KEY (`id`)
หมายความว่า:
id 100
สามารถมีได้เพียงหนึ่ง Row
ดังนั้น:
100
100
ใน Primary Key เดียวกันไม่ได้
③ UNIQUE KEY คืออะไร
UNIQUE Constraint ใช้ป้องกันค่าซ้ำใน Column หรือชุด Columns ที่กำหนดให้ต้อง Unique.
ตัวอย่าง FiveM:
UNIQUE KEY `identifier`
(`identifier`)
หากมี:
license:abc123
อยู่แล้ว
แล้ว Resource พยายาม Insert:
license:abc123
อีกครั้ง จะเกิด Duplicate Entry
④ PRIMARY KEY กับ UNIQUE KEY ต่างกันอย่างไร
แนวคิดง่ายๆ:
PRIMARY KEY
→ ตัวระบุหลักของ Row
→ ต้อง Unique
→ ต้อง NOT NULL
ส่วน:
UNIQUE KEY
→ บังคับความไม่ซ้ำของข้อมูลบาง Column
MariaDB ระบุว่า Primary Key เป็น Constraint ที่ต้อง Unique และ NOT NULL ขณะที่ Unique Constraint ใช้ป้องกันค่าซ้ำตาม Key ที่กำหนด.
⑤ FiveM Duplicate Entry เกิดจากอะไรบ่อยที่สุด
สาเหตุที่ควรตรวจก่อน:
① INSERT Player ซ้ำ
② INSERT Character ซ้ำ
③ ใช้ Identifier เดิม
④ Primary ID ถูกกำหนดเองแล้วซ้ำ
⑤ AUTO_INCREMENT ไม่สัมพันธ์กับข้อมูล
⑥ Import SQL ซ้ำ
⑦ Restore Backup ทับ Database เดิม
⑧ Resource เริ่มพร้อมกันและ Insert Record เดียวกัน
⑨ Script ควร UPDATE แต่กลับ INSERT
⑩ UNIQUE KEY ถูกตั้งกับ Column ที่ Business Logic อนุญาตให้ซ้ำ
MariaDB Error 1062 บอกเพียงว่าค่า Unique/Primary ซ้ำ ดังนั้นต้องดูชื่อ Key และค่าที่ซ้ำเพื่อหา Root Cause.
⑥ อ่าน Error ให้ครบก่อนแก้
สมมติ Error:
Duplicate entry 'license:xyz'
for key 'identifier'
ข้อมูลสำคัญมี 2 ส่วน:
ค่าที่ซ้ำ
=
license:xyz
และ:
Key ที่ชน
=
identifier
อย่าเห็นเพียง:
1062
แล้วเริ่มลบข้อมูล
ต้องหาก่อนว่า Key นั้นอยู่ Table ไหนและถูกสร้างไว้เพื่ออะไร
⑦ วิธีดูโครงสร้าง Table
ใช้:
SHOW CREATE TABLE `users`;
เพื่อดูว่า Table มี:
PRIMARY KEY
UNIQUE KEY
INDEX
อะไรบ้าง
MariaDB มี SHOW CREATE TABLE สำหรับแสดง Definition ที่ใช้สร้าง Table ซึ่งเป็นวิธีสำคัญในการตรวจ Constraints และ Index Structure จริงของ Schema.
⑧ ตัวอย่างตรวจ UNIQUE KEY
สมมติได้:
CREATE TABLE `users` (
`id` INT NOT NULL AUTO_INCREMENT,
`identifier` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `identifier` (`identifier`)
);
แปลว่า:
id
→ ห้ามซ้ำ
identifier
→ ห้ามซ้ำ
ดังนั้น Error 1062 สามารถเกิดจาก Key ตัวใดตัวหนึ่งได้
⑨ ตรวจข้อมูลที่มีอยู่ก่อน
ถ้า Error บอก:
Duplicate entry 'license:abc123'
for key 'identifier'
ตรวจ:
SELECT *
FROM `users`
WHERE `identifier` = 'license:abc123';
ถ้าพบ Row อยู่แล้ว ให้ถามต่อว่า:
Resource ควรสร้าง Row ใหม่จริงหรือ?
หรือควร:
UPDATE Row เดิม?
นี่เป็นจุดสำคัญที่สุด
⑩ INSERT หรือ UPDATE ต้องเลือกให้ถูก
สมมติ Player มี Row อยู่แล้ว
แต่ทุกครั้งที่ Join Resource ทำ:
INSERT INTO `users`
(`identifier`, `last_seen`)
VALUES
(?, NOW());
Player คนเดิมเข้าอีกครั้ง:
identifier เดิม
↓
INSERT ใหม่
↓
Duplicate Entry
ถ้าความต้องการคืออัปเดต last_seen อาจต้องใช้ UPDATE หรือ Upsert ตาม Business Logic
⑪ UPDATE เหมาะเมื่อ Row ต้องมีอยู่แล้ว
ตัวอย่าง:
UPDATE `users`
SET `last_seen` = NOW()
WHERE `identifier` = ?;
oxmysql มี MySQL.update ซึ่งคืนจำนวน Rows ที่ได้รับผลจาก Query.
แนวคิดคือ:
Player มีอยู่แล้ว
→ UPDATE
ไม่ใช่:
Player มีอยู่แล้ว
→ INSERT ใหม่
⑫ Upsert คืออะไร
MariaDB รองรับ:
INSERT ... ON DUPLICATE KEY UPDATE
ซึ่งหากพบ Duplicate บน Unique หรือ Primary Key จะเปลี่ยนไป Execute UPDATE แทนการจบด้วย Error 1062.
ตัวอย่าง:
INSERT INTO `users`
(
`identifier`,
`last_seen`
)
VALUES
(
?,
NOW()
)
ON DUPLICATE KEY UPDATE
`last_seen` = NOW();
เหมาะกับ Use Case ที่นิยามชัดว่า:
ไม่มี Row
→ INSERT
มี Row แล้ว
→ UPDATE
⑬ อย่าใช้ Upsert แก้ทุก Duplicate Error
เพราะ Duplicate บางกรณีคือ Bug
ตัวอย่าง:
Character ID ควรใหม่ทุกครั้ง
แต่กลับซ้ำ
ถ้าเปลี่ยนเป็น Upsertทันที:
Character ใหม่
↓
ชน Character เดิม
↓
UPDATE Character เดิม
อาจทำข้อมูลเสียหนักกว่า Error เดิม
ใช้ Upsert เฉพาะเมื่อ Business Logic ต้องการ:
Insert-or-update
จริงๆ
⑭ INSERT IGNORE คืออะไร
MariaDB รองรับ INSERT IGNORE ซึ่งสามารถเปลี่ยน Errors บางประเภท รวมถึง Duplicate Key Errors ให้เป็น Warnings และดำเนินการตาม Behavior ของ IGNORE.
ตัวอย่าง:
INSERT IGNORE INTO `users`
(
`identifier`
)
VALUES
(
?
);
แต่ ไม่ควรใช้เพื่อซ่อน Error แบบสุ่ม
เพราะ:
Query ไม่ Insert
แต่ Resource อาจคิดว่า Insert แล้ว
ทำให้ Runtime Logic ผิด
⑮ INSERT IGNORE กับ Upsert ต่างกัน
INSERT IGNORE
เมื่อเจอ Duplicate:
ไม่ Insert Duplicate Row ตามปกติ
และเปลี่ยน Error เป็น Warning ตาม Behavior
ON DUPLICATE KEY UPDATE
เมื่อเจอ Duplicate:
UPDATE Row ที่ชน
MariaDB แยก Behavior สองแบบนี้อย่างชัดเจน.
เลือกตาม Business Logic ไม่ใช่เลือกเพียงเพื่อให้ Console ไม่มี Error
⑯ Duplicate PRIMARY KEY หลัง Import SQL
สมมติ Database มี:
id 1
id 2
id 3
แล้ว Import Backup ที่มี:
id 1
id 2
id 3
อีกครั้ง
จะชน Primary Keys
MariaDB จะ Error เพราะ Primary Key ต้องระบุแต่ละ Row อย่างไม่ซ้ำ.
ก่อน Import ต้องรู้ว่าเป็น:
Full Restore
Merge
Migration
Seed Data
เพราะวิธีจัดการต่างกัน
⑰ อย่า Import Backup ซ้ำลง Database เดิมแบบไม่ตรวจ
ถ้า Backup เป็น Full Dump:
CREATE TABLE
INSERT Data
แต่ Database ปัจจุบันมีข้อมูลอยู่แล้ว
การนำ INSERT เดิมกลับมารันอาจสร้าง Duplicate Keys
ควร Restore ลง:
Test Database
ก่อนเพื่อดูโครงสร้างและข้อมูล
⑱ Duplicate หลัง Restore Backup
อาจเกิดจาก:
Restore ซ้ำ
Restore บาง Table สองครั้ง
Merge สอง Backup
Import Production ทับ Production
ต้องหาก่อนว่าข้อมูลไหนคือ Version ที่ถูกต้อง
อย่าลบ Duplicateโดยใช้:
DELETE ...
แบบกว้างจนข้อมูล Production หาย
⑲ AUTO_INCREMENT คืออะไร
Primary Key บาง Table ใช้:
AUTO_INCREMENT
เพื่อให้ MariaDB สร้างเลข ID ใหม่อัตโนมัติ
ตัวอย่าง:
`id` INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
ถ้า Resource ไม่จำเป็นต้องกำหนด ID เอง ควรปล่อย Databaseสร้าง ID ตาม Data Model ที่ออกแบบไว้ แทนการส่งเลขที่อาจชนเอง
⑳ อย่าใส่ ID เองถ้า Database ควรสร้าง
ตัวอย่างที่เสี่ยง:
local id = 100
MySQL.insert.await(
'INSERT INTO characters (id, name) VALUES (?, ?)',
{
id,
name
}
)
ถ้า id=100 มีอยู่แล้ว:
Duplicate entry '100'
for key 'PRIMARY'
ถ้า Table ออกแบบให้ AUTO_INCREMENT ควรตรวจว่าจำเป็นต้องส่ง ID จริงหรือไม่
㉑ วิธีดูค่าที่ oxmysql Insert ได้
oxmysql MySQL.query สามารถคืนข้อมูลอย่าง insertId และ affectedRows สำหรับ Statements ที่เกี่ยวข้อง ขณะที่ API อื่นของ oxmysql ก็มี Return Values สำหรับ Insert/Update Operations.
ดังนั้น Resource ควรใช้ค่าที่ Databaseคืนมาอย่างถูกต้อง แทนสร้าง ID ซ้ำเองเมื่อไม่มีความจำเป็น
㉒ Race Condition ทำ Duplicate Entry ได้
ตัวอย่าง:
Request A
SELECT identifier
→ ไม่มี
Request B
SELECT identifier
→ ไม่มี
จากนั้นพร้อมกัน:
A → INSERT
B → INSERT
หนึ่ง Query ผ่าน
อีก Query:
Duplicate Entry
เพราะการ:
SELECT ก่อน INSERT
ไม่ได้ทำให้สอง Requests กลายเป็น Atomic Operation
㉓ UNIQUE KEY มีประโยชน์กับ Race Condition
ถึง Application เช็กก่อน Insert Database-level UNIQUE Constraint ยังคงเป็นชั้นสุดท้ายที่ป้องกันข้อมูลซ้ำจาก Concurrent Requests. MariaDB Constraints มีหน้าที่บังคับ Data Integrity โดยตรง.
ดังนั้น อย่าลบ UNIQUE KEY เพื่อแก้ Race Condition
ควรแก้ Application Flow
㉔ Upsert ช่วย Race Condition บางกรณี
ถ้า Business Logic เป็น:
มีแล้ว
→ Update
ไม่มี
→ Insert
INSERT ... ON DUPLICATE KEY UPDATE ช่วยให้การจัดการ Duplicate Unique/Primary Key อยู่ใน Statement เดียว.
จึงเหมาะกว่ารูปแบบ:
SELECT
↓
ถ้าไม่มี
↓
INSERT
ในหลาย Use Case
㉕ Transaction ช่วยไหม
oxmysql ระบุว่า MySQL.transaction ใช้ Execute หลาย Queries และ Commit เฉพาะเมื่อทุก Query สำเร็จ หาก Query หนึ่งล้มเหลวจะไม่ Commit ทั้งชุด.
เหมาะเมื่อ Duplicate Error เกิดภายใน Workflow เช่น:
Create Character
+
Create Settings
+
Create Metadata
ที่ต้องสำเร็จพร้อมกัน
แต่ Transaction ไม่ได้ทำให้ Duplicate Key หาย หากค่าที่ Insert ซ้ำจริง
㉖ Duplicate Entry ภายใน Transaction
ตัวอย่าง:
Transaction
Query 1
→ INSERT Character
Query 2
→ INSERT Unique Identifier ซ้ำ
→ Error 1062
ถ้าใช้ MySQL.transaction ตาม oxmysql และ Query หนึ่งล้มเหลว จะไม่มี Queries ในชุด Transaction นั้นถูก Commit.
นี่ช่วยป้องกันข้อมูลครึ่งชุด
㉗ Error 1062 หลัง Player Join
ถ้าเกิดทุกครั้งที่ Player เข้า Server ให้ตรวจ Resource ที่ทำ:
On player joining
↓
INSERT User
ถามว่า:
ควรสร้าง User เฉพาะครั้งแรกหรือไม่?
ถ้าใช่ Logic ต้องแยก:
New Player
จาก:
Existing Player
อย่างถูกต้อง
㉘ Error 1062 หลัง Character Create
ตรวจ:
Character ID
Character Identifier
Slot Number
Unique Character Name
ว่าตัวไหนถูกกำหนดเป็น Unique
สมมติ Constraint:
UNIQUE KEY `identifier_slot`
(
`identifier`,
`slot`
)
Player เดียวอาจสร้างหลาย Character ได้ แต่:
identifier + slot
ชุดเดียวกันห้ามซ้ำ
ต้องดู Composite Key จริง
㉙ Composite UNIQUE KEY คืออะไร
Unique Constraint ไม่จำเป็นต้องมีเพียง Column เดียว
ตัวอย่าง:
UNIQUE KEY `identifier_slot`
(
`identifier`,
`slot`
)
หมายความว่าคู่:
identifier=A
slot=1
ห้ามมีซ้ำอีกชุดหนึ่ง
แต่:
identifier=A
slot=2
อาจใช้ได้
ดังนั้น Error:
Duplicate entry 'A-1'
อาจมาจาก Composite Key ไม่ใช่ Column เดียว
㉚ ดู Composite Key อย่างไร
ใช้:
SHOW CREATE TABLE `characters`;
แล้วหา:
UNIQUE KEY
หรือ:
PRIMARY KEY
ที่มีหลาย Columns
อย่าเดาจากชื่อ Error Key เพียงอย่างเดียว
㉛ UNIQUE กับ NULL ต้องเข้าใจ
MariaDB ระบุว่า Unique Index สามารถมี NULL หลายค่าได้ เพราะ SQL ไม่ถือว่า NULL หนึ่งเท่ากับ NULL อีกตัวในบริบทนี้.
ดังนั้น:
NULL
NULL
ไม่ได้มี Duplicate Behavior แบบค่าจริงทั่วไปเสมอไป
นี่สำคัญเมื่อออกแบบ Optional Identifiers
㉜ Error 1062 หลัง Script Update
ตรวจ:
Migration เพิ่ม UNIQUE KEY หรือไม่
Resource เปลี่ยน Identifier Format หรือไม่
Seed Data ถูก Insert ใหม่หรือไม่
Default Records ถูกสร้างซ้ำหรือไม่
ตัวอย่าง:
Version ใหม่เพิ่ม:
UNIQUE KEY (`identifier`)
แต่ Database เก่ามี Duplicate Identifiers อยู่แล้ว
Migration อาจล้มเหลวหรือ Runtime Insert เริ่มเจอ Error หลัง Update
㉝ ก่อนเพิ่ม UNIQUE ต้องตรวจข้อมูลเก่า
ตัวอย่างหา Duplicate:
SELECT
`identifier`,
COUNT(*) AS `total`
FROM `users`
GROUP BY `identifier`
HAVING COUNT(*) > 1;
ถ้าได้:
identifier A = 3 rows
identifier B = 2 rows
แปลว่ามี Data Duplication อยู่แล้ว
ก่อนสร้าง Unique Constraint ต้องตัดสินใจว่า Row ไหนถูกต้อง
㉞ วิธีหา Duplicate Character ID
SELECT
`character_id`,
COUNT(*) AS `total`
FROM `characters`
GROUP BY `character_id`
HAVING COUNT(*) > 1;
ใช้หลักเดียวกัน
แต่ถ้า character_id เป็น Primary Key ที่ Constraint ทำงานอยู่แล้ว ปกติ Databaseจะไม่ยอมให้ Duplicate ถูก Insert เข้ามาตั้งแต่ต้น.
Duplicate Existing Data มักบ่งชี้ว่าช่วงหนึ่ง Constraint ไม่ได้อยู่ใน Schema หรือข้อมูลมาจากกระบวนการอื่น
㉟ Duplicate Character Name ไม่ได้แปลว่าผิดเสมอ
อย่าตั้ง:
UNIQUE(name)
เพียงเพราะต้องการป้องกัน Duplicate โดยไม่ดู Game Design
ผู้เล่นสองคนอาจอนุญาตให้ใช้ชื่อเดียวกันได้ตาม Server Rules
Unique Constraint ต้องสะท้อน Business Rule จริง
ไม่ใช่สิ่งที่ Developerรู้สึกว่าน่าจะ Unique
㊱ Identifier แบบไหนควร Unique
ขึ้นกับ Framework/Data Model เช่น:
Account Identifier
Character Internal ID
Database Primary ID
บางตัวควร Unique
บางตัว:
Display Name
Nickname
Job Label
อาจไม่ควร Unique
อย่ากำหนด Constraint ก่อนเข้าใจ Domain
㊲ Duplicate Entry หลังเปลี่ยน Identifier Format
ตัวอย่างเดิม:
license:abc
ใหม่:
abc
Migration อาจทำให้ Records ที่เคยต่างกันถูก Normalize แล้วชนกัน
ก่อนเปลี่ยน Format ต้องตรวจ:
Old Values
New Values
Collision
ไม่ใช่ Update ทุก Row แล้วหวังว่าจะผ่าน
㊳ Duplicate Entry จาก Default Data
บาง Resource ตอน Startup ทำ:
INSERT INTO `settings`
VALUES ('default', ...);
ทุกครั้งที่ Resource Start
ครั้งแรกผ่าน
ครั้งต่อมา:
Duplicate Entry
สำหรับ Default/Configuration Rows ที่ควรมีเพียงหนึ่งตัว ควรใช้ Migration/Seed Logic ที่รองรับการรันซ้ำอย่างปลอดภัย หรือใช้ Upsert เมื่อ Business Logic เหมาะสม. MariaDB รองรับ ON DUPLICATE KEY UPDATE สำหรับกรณี Insert-or-update.
㊴ Idempotent Migration คืออะไร
แนวคิดคือ:
รันครั้งแรก
→ สำเร็จ
รันครั้งที่สอง
→ ไม่ทำข้อมูลซ้ำหรือเสีย
เช่น Seed Data ไม่ควร Insert Duplicate ทุกครั้งที่ Resource Restart
การออกแบบ Migration/Setup Script ให้รันซ้ำได้อย่างปลอดภัยช่วยลด Error 1062
㊵ อย่าให้ Resource Insert Seed Data ทุก Tick
นี่ผิด Architecture ชัดเจน
while true
↓
INSERT default
↓
Duplicate
↓
Error
Seed/Migration Data ควรถูกจัดการตอน Install/Upgrade หรือ Initialization ที่มี Guard ถูกต้อง
ไม่ใช่ Runtime Loop
㊶ Duplicate Entry หลัง Resource Restart
ถ้าเกิดเฉพาะ:
restart my_resource
ให้ตรวจ Startup Handler
อาจมี:
onResourceStart
↓
INSERT default record
แต่ไม่ได้ตรวจว่า Record มีอยู่แล้ว
แก้ Startup Logic
ไม่ใช่ล้าง Table ทุกครั้งที่ Restart
㊷ Duplicate Entry หลัง Server Restart
หาก Error เกิดทุกครั้งที่ FXServer เปิด:
FXServer Start
↓
Resources Start
↓
หลาย Resource Insert Seed Data
ตรวจ Resource Dependencies และ Initialization
บางครั้ง Resource A กับ Resource B ต่างคิดว่าตัวเองต้องสร้าง Row เดียวกัน
㊸ Resource สองตัว Insert ค่าเดียวกัน
ตัวอย่าง:
resource_a
→ INSERT account
resource_b
→ INSERT account
เมื่อ Player Join พร้อมกัน:
A ผ่าน
B Error 1062
ต้องกำหนด Ownership ของ Data ให้ชัดว่า:
Resource ไหนมีหน้าที่สร้าง Row?
อีก Resource ควรอ่านหรือ Update แทน
㊹ Duplicate Entry หลังกด Action ซ้ำ
ผู้เล่นกด Button สองครั้งเร็วมาก:
Request 1
Request 2
Server รับ Events ซ้ำ
ทั้งสองพยายามสร้าง Record เดียวกัน
Unique Constraint จึงป้องกัน Duplicate Data ได้
แก้เพิ่มเติมด้วย:
Server-side state
Debounce
Idempotency
Atomic database logic
ตาม Use Case
㊺ อย่าเชื่อ Client ว่า Action เกิดครั้งเดียว
FiveM Resource ต้องตรวจฝั่ง Server
เพราะ Client Event สามารถ:
ยิงซ้ำ
ส่งค่าซ้ำ
ถูก Trigger มากกว่าหนึ่งครั้ง
Database Unique Constraint เป็น Safety Layer หนึ่ง แต่ Application Logic ยังต้องจัดการ Duplicate Requests
㊻ Duplicate Entry จาก Retry
สมมติ Query Insert สำเร็จแล้ว แต่ Applicationไม่ได้รับ Response ตามที่คาดและ Retry:
Attempt 1
→ Insert สำเร็จ
Attempt 2
→ Insert ค่าเดิม
→ 1062
ถ้า Operation รองรับ Retry ควรออกแบบ:
Idempotency
Unique Operation ID
Upsert
ตาม Business Requirement
ไม่ใช่ Retry INSERT เดิมไม่จำกัดครั้ง
㊼ Error 1062 ไม่ควร Retry แบบเดิมทันที
ถ้าค่าซ้ำจริง:
Retry 1
→ 1062
Retry 2
→ 1062
Retry 100
→ 1062
เพราะ Unique Constraint ยังเหมือนเดิม
ต้อง:
เปลี่ยน Operation
เปลี่ยน Value
UPDATE Row เดิม
หรือแก้ข้อมูลต้นเหตุ
㊽ mysql_debug ช่วยอะไร
oxmysql ระบุว่า Real Query Speeds และข้อมูล Debug สามารถดูจาก Debug UI/Server Console เมื่อเปิด mysql_debug; Performance ขึ้นกับ Hardware, Database Settings, Version และ Workload.
เมื่อเจอ Duplicate ให้ใช้ Debug เพื่อจับ:
Resource
SQL
Parameters
เวลาเกิด
โดยเฉพาะกรณี Error เกิดเป็นช่วงๆ
㊾ ดู Query อย่างเดียวไม่พอ
ตัวอย่าง SQL:
INSERT INTO users (identifier)
VALUES (?);
ดูแล้วไม่มีอะไรผิด
แต่ Parameter จริง:
license:abc123
ถูก Insert ไปแล้ว
ดังนั้นต้องจับ:
SQL
+
Parameter
คู่กัน
㊿ Duplicate Entry กับ Foreign Key Error ต่างกัน
Error 1062
ค่าที่ต้อง Unique ซ้ำ
Error 1452
Child อ้าง Parent ที่ไม่มี
สองตัวเป็น Constraint Errors เหมือนกันในภาพรวม แต่ Root Cause คนละแบบ
ห้ามใช้วิธีแก้เดียวกัน
51. Duplicate Entry กับ Duplicate Key Name ต่างกัน
MariaDB มี Error 1061:
Duplicate key name
ซึ่งหมายถึงชื่อ Key/Index ซ้ำใน Schema Definition ไม่ใช่ข้อมูล Row ซ้ำ.
ส่วน Error 1062 คือ:
Duplicate entry
หรือค่าข้อมูลชน Unique/Primary Key.
52. Error 1022 ต่างจาก 1062 อย่างไร
MariaDB มี Error 1022:
Can't write; duplicate key in table
เป็น Duplicate Key Error อีกประเภทหนึ่งในบาง Schema/Write Operations.
ดังนั้นควรอ่าน Error Code จริงก่อนแก้
ไม่ใช่เห็นคำว่า:
duplicate
แล้วสรุปว่าเป็น 1062 ทุกครั้ง
53. วิธีแก้ Error 1062 แบบ 5 นาที
เมื่อ Console ขึ้น Duplicate Entry:
① จด Table
② จด Duplicate Value
③ จด Key Name
④ SHOW CREATE TABLE
⑤ หา PRIMARY/UNIQUE Constraint
⑥ SELECT หาค่าที่ซ้ำ
⑦ หา Resource ที่ Insert
⑧ ดู Parameters จริง
⑨ ถามว่าควร INSERT หรือ UPDATE
⑩ ตรวจว่า Upsert เหมาะหรือไม่
อย่าเริ่มจาก DELETE Row ที่ซ้ำทันที
54. ตัวอย่าง Debug จริง
Error:
Duplicate entry 'license:abc'
for key 'identifier'
ตรวจ:
SELECT *
FROM `users`
WHERE `identifier` = 'license:abc';
ถ้าพบ:
1 Row
ดูต่อว่า Resource ทำ:
INSERT users
ทุกครั้งตอน Join หรือไม่
หาก Row นั้นเป็น Player คนเดิม อาจต้อง Update ไม่ใช่สร้าง User ใหม่
55. ถ้าพบ 2 Rows ที่ควร Unique อยู่แล้ว
ถ้า Schema ตอนนี้ไม่มี Unique Constraint แต่ข้อมูลมี:
A
A
ก่อนเพิ่ม UNIQUE ต้องตัดสินว่า:
Row ไหนถูก
Row ไหนซ้ำ
ข้อมูลแต่ละ Row มีความสำคัญอะไร
Backup ก่อน Merge/Delete
อย่าใช้:
DELETE
โดยไม่ตรวจ Foreign Keys และ Related Data
56. ถ้าค่าที่ Duplicate ไม่ควรซ้ำจริง
เช่น Internal Character ID
Root Cause อาจเป็น:
ID Generator
AUTO_INCREMENT
Manual ID
Race Condition
Restore
ต้องแก้ที่ Generator/Data Source
ไม่ใช่เปลี่ยน Primary Key ให้รับ Duplicate เพราะ Primary Key มีหน้าที่ระบุ Rows อย่างไม่ซ้ำ.
57. ถ้าค่าที่ Duplicate ควรซ้ำได้
กรณีนี้อาจเป็น Schema Design Problem
เช่น:
display_name
ถูกตั้ง:
UNIQUE
แต่ Server Rules อนุญาตชื่อซ้ำ
จึงต้องประเมินว่า Unique Constraint ถูกสร้างผิด Requirement หรือไม่
ก่อน:
DROP INDEX
ควร Backup และตรวจว่ามี Resource ไหนพึ่ง Constraint นี้อยู่
58. CREATE INDEX กับ UNIQUE ต่างกัน
Plain Index:
ช่วย Access/Query
แต่ไม่ได้บังคับค่าห้ามซ้ำ
MariaDB ระบุว่า Plain Index ไม่ใช่ Unique, Primary หรือ Foreign Key Index.
ดังนั้นการเปลี่ยนจาก:
UNIQUE INDEX
เป็น:
INDEX
มีผลต่อ Data Integrity ไม่ใช่แค่ Performance
59. อย่าลบ UNIQUE เพื่อให้ Script เก่าทำงาน
ถ้า Official Schema Version ใหม่เพิ่ม Unique Constraint อาจเป็นเพราะ Resource ต้องการรับประกันข้อมูลบางอย่าง
การลบ Constraint อาจทำให้:
Script ไม่ Error
แต่ Database มีข้อมูลซ้ำ
และ Error ไปเกิดภายหลังใน:
SELECT
JOIN
Update
Character Load
แก้ Resource/Data ให้ตรง Schema ก่อน
60. Checklist Duplicate Entry FiveM
ตรวจทั้งหมดนี้:
Error Code ใช่ 1062 หรือไม่
Duplicate Value คืออะไร
Key Name คืออะไร
Table ไหน
Key เป็น PRIMARY หรือ UNIQUE
Composite Key หรือไม่
Existing Row มีอยู่หรือไม่
Existing Row เป็นข้อมูลที่ถูกต้องหรือไม่
Resource ไหนยิง INSERT
Parameters จริงคืออะไร
Query ควรเป็น INSERT หรือ UPDATE
Upsert เหมาะหรือไม่
INSERT IGNORE เหมาะจริงหรือไม่
มี Race Condition หรือไม่
Event ถูกยิงซ้ำหรือไม่
Resource สองตัวสร้างข้อมูลเดียวกันหรือไม่
Startup Insert ซ้ำหรือไม่
Seed Data ซ้ำหรือไม่
Migration รันสองครั้งหรือไม่
Backup ถูก Import ซ้ำหรือไม่
Restore ทับข้อมูลเดิมหรือไม่
AUTO_INCREMENT ทำงานตาม Schema หรือไม่
Resource กำหนด ID เองหรือไม่
Identifier Format เปลี่ยนหรือไม่
Unique Constraint สอดคล้อง Business Rule หรือไม่
Query อยู่ใน Transaction หรือไม่
Partial Data ถูก Commit ก่อน Error หรือไม่
Backup ก่อน Cleanup แล้วหรือไม่
Test บน Staging หรือไม่
Monitor หลังแก้แล้วหรือไม่
ตาราง Duplicate Error ที่ควรรู้
| Error | ความหมาย |
|---|---|
1062 | Duplicate Entry บน Unique/Primary Key |
1061 | Duplicate Key Name |
1022 | Can't write; duplicate key in table |
1452 | Foreign Key Child ไม่มี Parent |
| Unknown Column | Schema/Column ไม่ตรง |
| Table Doesn't Exist | Table ไม่มี |
MariaDB แยก Error เหล่านี้เป็นคนละ Error Codes ดังนั้นต้องแก้ตาม Code และ Context จริง.
FiveM Duplicate Entry for Key PRIMARY แก้อย่างไร
ถ้า Error เป็น:
Duplicate entry '100'
for key 'PRIMARY'
ให้ตรวจ:
SELECT *
FROM `table_name`
WHERE `id` = 100;
จากนั้นตรวจว่า Resource กำลัง:
กำหนด ID เอง
หรือ Database ควรสร้าง ID ให้
MariaDB ระบุว่า Primary Key ต้องระบุ Row แต่ละ Rowอย่างไม่ซ้ำ ดังนั้นการ Insert Primary Key เดิมซ้ำจะเกิด Error 1062.
FiveM Duplicate Entry Identifier แก้อย่างไร
ตรวจว่า Identifier นั้นมี Row อยู่แล้วหรือไม่
ถ้าเป็น Existing Player และ Resource เพียงต้องอัปเดตข้อมูล:
UPDATE
หรือ Upsert อาจเหมาะกว่า INSERT ใหม่ตาม Business Logic
MariaDB รองรับ INSERT ... ON DUPLICATE KEY UPDATE เพื่อ Update เมื่อชน Unique/Primary Key.
FiveM Error 1062 หลัง Restart แก้อย่างไร
ตรวจ:
onResourceStart
Startup Migration
Seed Data
Initialization
หาก Script Insert Default Row ทุกครั้งที่ Restart ต้องทำ Initialization ให้ Idempotent หรือใช้ Insert-or-update เมื่อเหมาะสม
FiveM Error 1062 หลัง Import SQL แก้อย่างไร
ตรวจว่า SQL Dump ถูก Import ลง Database ที่มี Records ชุดเดียวกันอยู่แล้วหรือไม่
อย่า Import ซ้ำหลายรอบเพียงเพราะ Console ไม่มีข้อความ Success ที่คาด
ควร Restore บน Test Database ก่อน Production
FiveM Error 1062 หลัง Update Script
ตรวจ Migration ใหม่ โดยเฉพาะ:
UNIQUE KEY ใหม่
PRIMARY KEY ใหม่
Identifier Format
Seed Data
และตรวจ Existing Data ก่อนแก้ Constraint
FiveM Duplicate Entry ใช้ ON DUPLICATE KEY UPDATE ได้ไหม
ได้เมื่อ Business Logic ต้องการ:
ไม่มี
→ INSERT
มีแล้ว
→ UPDATE
MariaDB ระบุว่า INSERT ... ON DUPLICATE KEY UPDATE จะทำ UPDATE เมื่อพบ Duplicate Unique หรือ Primary Key.
FiveM ใช้ INSERT IGNORE ได้ไหม
MariaDB รองรับ แต่ IGNORE จะเปลี่ยน Errors ให้เป็น Warnings ตาม Behavior ของคำสั่ง รวมถึง Duplicate Key Cases.
จึงไม่ควรใช้เพียงเพื่อซ่อน Bug
FiveM Duplicate Entry ใช้ Transaction ช่วยไหม
ช่วยรักษา Atomicity ของ Workflow หลาย Queries ได้
oxmysql MySQL.transaction จะ Commit เมื่อทุก Query สำเร็จ และไม่ Commit หากหนึ่ง Query ล้มเหลว.
แต่ถ้า Duplicate Value ผิดจริง Transaction ไม่สามารถแก้ค่านั้นให้เองได้
FiveM Duplicate Entry เกิดจากผู้เล่นกดซ้ำได้ไหม
ได้ หาก Requests หลายตัวพยายาม Insert Record เดียวกันพร้อมกัน
Unique Constraint จะช่วยป้องกันไม่ให้ข้อมูลซ้ำถูก Commit แต่ Application ควรเพิ่ม Server-side Protection สำหรับ Duplicate Requests
FiveM ลบ UNIQUE KEY เพื่อแก้ดีไหม
ไม่ควรเป็นขั้นแรก
MariaDB Constraints ใช้บังคับ Data Integrity ดังนั้นต้องพิสูจน์ก่อนว่า Constraint นั้นผิด Business Requirement จริง ไม่ใช่ Resource เป็นฝ่าย Insert ข้อมูลผิด.
FAQ FiveM MariaDB Duplicate Entry
Error 1062 คืออะไร
คือ MariaDB ER_DUP_ENTRY ซึ่งเกิดเมื่อค่าที่ต้อง Unique หรือเป็น Primary Key ซ้ำกับค่าที่มีอยู่.
Duplicate entry for key PRIMARY คืออะไร
หมายถึง Primary Key ที่กำลัง Insert ซ้ำกับ Row ที่มีอยู่แล้ว.
Duplicate entry for key identifier คืออะไร
หมายถึง Key/Unique Index ชื่อ identifier พบค่าซ้ำ ต้องตรวจว่า Existing Row คืออะไรและ Resource ควร Insert ใหม่จริงหรือไม่
PRIMARY KEY ซ้ำได้ไหม
ไม่ได้ Primary Key ต้อง Unique และไม่เป็น NULL.
UNIQUE KEY มีค่าซ้ำได้ไหม
ค่าปกติที่อยู่ภายใต้ Unique Constraint ต้องไม่ซ้ำ แต่ MariaDB ระบุว่า Unique Index สามารถมี NULL หลายค่าได้.
ใช้ Upsert แก้ Duplicate ได้ไหม
ได้เมื่อ Business Logic เป็น Insert-or-update โดย MariaDB รองรับ ON DUPLICATE KEY UPDATE.
INSERT IGNORE ควรใช้ไหม
ใช้ได้ใน Use Case ที่เข้าใจ Behavior จริง แต่ไม่ควรใช้เพื่อซ่อน Error เพราะ Duplicate Errors สามารถถูกเปลี่ยนเป็น Warnings.
Transaction ป้องกัน Duplicate ได้ไหม
Unique Constraint เป็นตัวป้องกัน Duplicate โดยตรง ส่วน Transaction ช่วยให้หลาย Queries Commit หรือ Fail เป็นชุดเดียวกัน.
Error 1062 หลัง Restore เกิดได้ไหม
ได้ หากนำ Records ที่มี Primary/Unique Keys เดิมไป Insert ทับข้อมูลที่มีอยู่แล้ว
Error 1062 หลัง Resource Restart เกิดได้ไหม
ได้ โดยเฉพาะ Script ที่ Insert Seed/Default Records ทุกครั้งที่ Start โดยไม่มี Idempotent Logic
ควรลบ Row ที่ Duplicate ไหม
ต้องตรวจว่า Row ไหนถูกก่อน โดยเฉพาะ Production Database ควร Backup ก่อน Merge/Delete Data
ควรลบ UNIQUE INDEX ไหม
ไม่ควร เว้นแต่พิสูจน์แล้วว่า Constraint ไม่ตรง Business Rule จริง เพราะ Constraint มีหน้าที่ป้องกันข้อมูลที่ไม่ถูกต้อง.
ประเด็นสำคัญ
เมื่อ FiveM ขึ้น:
ERROR 1062
Duplicate entry
ให้ใช้ลำดับนี้:
Duplicate Value
↓
Key Name
↓
SHOW CREATE TABLE
↓
หา PRIMARY / UNIQUE KEY
↓
SELECT Existing Row
↓
หา Resource ที่ INSERT
↓
ตรวจ Parameters
↓
ตัดสินว่า INSERT / UPDATE / UPSERT
↓
แก้ Root Cause
MariaDB ระบุชัดว่า Error 1062 เกิดเมื่อ Key ที่ต้อง Unique ได้รับค่าซ้ำ และ Primary Key เองก็ต้องไม่ซ้ำทุก Row.
ถ้า Business Logic คือ “สร้างถ้ายังไม่มี แต่อัปเดตถ้ามีแล้ว” สามารถพิจารณา INSERT ... ON DUPLICATE KEY UPDATE ซึ่ง MariaDB รองรับโดยตรง. แต่ถ้าข้อมูลนั้น ไม่ควรซ้ำตั้งแต่แรก เช่น Primary Character ID การใช้ Upsert เพื่อทำให้ Error หายอาจซ่อน Bug และเขียนทับ Row ที่มีอยู่
สำหรับ Workflow หลาย Queries ที่ต้องสำเร็จพร้อมกัน MySQL.transaction ของ oxmysql ช่วยให้ Commit เฉพาะเมื่อทุก Query สำเร็จ. แต่ Unique Constraint ยังคงเป็นกลไกสำคัญที่ป้องกัน Duplicate Data ในระดับ Database โดยเฉพาะเมื่อมี Concurrent Requests
สำหรับผู้อ่าน comsiam ให้จำสูตร “1062 → ดูค่าที่ซ้ำ → ดู Key → หาเหตุผลว่าทำไมถึง INSERT ซ้ำ” และ comsiam แนะนำว่าอย่าลบ PRIMARY KEY หรือ UNIQUE KEY เพียงเพื่อให้ Console เงียบ เพราะ Error ที่เห็นตอนนี้มักดีกว่าการปล่อยข้อมูลซ้ำเข้า Database แล้วไปสร้างปัญหา Character, Account หรือ Resource ที่แก้ยากกว่าในภายหลัง
Comments
Post a Comment