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

ตรวจทั้งหมดนี้:

  1. Error Code ใช่ 1062 หรือไม่

  2. Duplicate Value คืออะไร

  3. Key Name คืออะไร

  4. Table ไหน

  5. Key เป็น PRIMARY หรือ UNIQUE

  6. Composite Key หรือไม่

  7. Existing Row มีอยู่หรือไม่

  8. Existing Row เป็นข้อมูลที่ถูกต้องหรือไม่

  9. Resource ไหนยิง INSERT

  10. Parameters จริงคืออะไร

  11. Query ควรเป็น INSERT หรือ UPDATE

  12. Upsert เหมาะหรือไม่

  13. INSERT IGNORE เหมาะจริงหรือไม่

  14. มี Race Condition หรือไม่

  15. Event ถูกยิงซ้ำหรือไม่

  16. Resource สองตัวสร้างข้อมูลเดียวกันหรือไม่

  17. Startup Insert ซ้ำหรือไม่

  18. Seed Data ซ้ำหรือไม่

  19. Migration รันสองครั้งหรือไม่

  20. Backup ถูก Import ซ้ำหรือไม่

  21. Restore ทับข้อมูลเดิมหรือไม่

  22. AUTO_INCREMENT ทำงานตาม Schema หรือไม่

  23. Resource กำหนด ID เองหรือไม่

  24. Identifier Format เปลี่ยนหรือไม่

  25. Unique Constraint สอดคล้อง Business Rule หรือไม่

  26. Query อยู่ใน Transaction หรือไม่

  27. Partial Data ถูก Commit ก่อน Error หรือไม่

  28. Backup ก่อน Cleanup แล้วหรือไม่

  29. Test บน Staging หรือไม่

  30. Monitor หลังแก้แล้วหรือไม่

ตาราง Duplicate Error ที่ควรรู้

Errorความหมาย
1062Duplicate Entry บน Unique/Primary Key
1061Duplicate Key Name
1022Can't write; duplicate key in table
1452Foreign Key Child ไม่มี Parent
Unknown ColumnSchema/Column ไม่ตรง
Table Doesn't ExistTable ไม่มี

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

Popular posts from this blog

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

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

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