Ask HN: ผมเจอการชนกันของ UUID v4 จริง ๆ...
(news.ycombinator.com)- วันนี้ฐานข้อมูลตรวจพบ UUID v4 ซ้ำกัน และค่าที่มีอยู่เดิมตรงกับ
b6133fd6-70fe-4fe3-bed6-8ca8fc9386cdของเรคคอร์ดที่ถูกเพิ่มในปี 2025 แบบตรงกันทุกประการ - แพ็กเกจที่ใช้อยู่คือ uuid ของ npm โดยระบุว่าใช้วิธี
import { v4 as uuidv4 } from "uuid";แล้วสร้างด้วยconst document_id = uuidv4();ก่อนนำไปใส่ในฐานข้อมูล - ในฐานข้อมูลมีเพียงประมาณ 15,000 เรคคอร์ด เท่านั้น จึงดูแทบเป็นไปไม่ได้ในเชิงสถิติ และกำลังถามว่ามีใครเคยเจอเรื่องแบบเดียวกันไหม
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
jandrewrogers: เรื่องนี้เกิดบ่อยกว่าที่คิดมาก ความปลอดภัยของ UUIDv4 ตั้งอยู่บนสมมติฐานว่ามีแหล่งเอนโทรปีคุณภาพสูง แต่สมมติฐานนี้พังได้ง่ายจากฮาร์ดแวร์เสีย บั๊กซอฟต์แวร์ทั่วไป หรือความเข้าใจเรื่องเอนโทรปีของนักพัฒนาที่ไม่เพียงพอ
การตรวจจับว่าแหล่งเอนโทรปีพังหรือเปล่ามีต้นทุนค่อนข้างสูง เลยแทบไม่มีใครทำ และก็มักจะรู้ตัวกันหลังจากเกิดการชนกันแล้วเท่านั้น ดังนั้นในระบบที่ต้องการความเชื่อถือสูงและการรับประกันสูงจำนวนมากจึงห้ามใช้ UUIDv4 อย่างชัดเจน
ยิ่งมีแหล่งเอนโทรปีมากก็ยิ่งดี และหลายแหล่งควรเป็นแบบไม่กำหนดแน่นอน แม้แต่ในเกมเล็ก ๆ ถ้าเอาค่าพิกัดเมาส์ ช่วงเวลาระหว่างการกดปุ่ม หรือจำนวนเฟรมก่อนกดปุ่มเริ่ม ไปผสมใน initial seed ก็จะทำให้เดายากขึ้นมาก แม้ภายในยังใช้ตัวสร้างเลขสุ่มเทียมอยู่ก็ตาม ถ้า CloudFlare ใช้แหล่งเอนโทรปีน้อยกว่า 100 แหล่งก็คงน่าผิดหวัง
สิ่งนี้เกิดขึ้นได้ถ้าไม่ตรวจค่าที่คืนกลับมาแบบที่เคยเกิดใน Go สมัยก่อน เช่น “ขอ N ไบต์ แต่ได้กลับมาแค่ 3 ไบต์ ดังนั้นต้องขออีก N-3 ไบต์” เพราะฮาร์ดแวร์หรือระบบปฏิบัติการส่วนใหญ่ไม่ค่อยทำให้ปัญหานี้โผล่ ผู้คนจึงไม่ตรวจสอบ จนวันหนึ่งมันไปโผล่ใน production เป็นการชนกันหลายหมื่นครั้ง
throwaway_19sz: ฟังดูตลกจนไม่น่าเชื่อแต่เป็นเรื่องจริง เมื่อ 10 ปีก่อนเพื่อนผมเข้าร่วมเป็น CTO ของสตาร์ตอัปโตเร็วแห่งหนึ่ง บริษัทมีนักพัฒนาประมาณ 200 คน และในสัปดาห์แรกก็พบว่ามี ไมโครเซอร์วิสสำหรับสร้าง UUID โดยเฉพาะ
มีวิศวกรดูแล endpoint เดียวถึง 3 คน แถมยังมีคนดูแลฐานข้อมูลอีกด้วย ถ้าทีมไหนต้องการ UUID “ที่ปลอดภัย” ตัวใหม่ ก็ต้องเรียกบริการนี้ทุกครั้ง บริการจะสร้าง UUID ขึ้นมา ตรวจใน DB ของตัวเองว่ามี UUID นี้เคยออกไปแล้วหรือไม่ ถ้าไม่มีก็ insert แล้วส่งกลับให้ ไม่รู้ว่าทำไปเพื่อความสบายใจหรือเปล่า แต่ทีมนั้นมีทั้งกระดานคัมบังและสปรินต์ของตัวเองด้วย
แต่สตาร์ตอัปที่เข้าทีหลังเป็นแบบที่ทุกครั้งที่มีคนคิดความกังวลใหม่ขึ้นมา ก็จะมีไมโครเซอร์วิสใหม่กับทีมใหม่เกิดขึ้น เป้าหมายรายไตรมาสระบุชัดเลยว่าต้องขยายขนาดทีมวิศวกรรม และทีมเล็ก ๆ 3-4 คนก็สร้างงานให้ตัวเองจากสปรินต์กับการประชุมวางแผนของตัวเอง ผมเคยเสนอให้ย้ายคนจากโปรเจกต์เสถียรไปช่วยงานด่วน แต่โดนคัดค้านเพราะขัดกับ KPI ที่ต้องเพิ่มจำนวนวิศวกรให้ถึงตัวเลขที่กำหนด
ถ้าต้องการ high availability และ deployment ทั่วโลก ก็ shard ได้ด้วยการให้ช่วง ID เฉพาะกับแต่ละ instance กันบิตส่วนบนบางส่วนไว้เป็น data center ID และอีกไม่กี่บิตสำหรับ instance ที่สร้าง ID ภายในนั้น เดี๋ยวก่อนนะ เหมือนเคยเห็นอะไรแบบนี้ที่ไหน… อยากรู้ว่า Twitter ยังใช้แนวนี้อยู่หรือสุดท้ายเปลี่ยนไปแล้ว
ทุกวันจะดึง DB dump มาเช็กตอนสร้าง ID “ชั่วคราว” และจะถือว่าเป็น “ยืนยันแล้ว” ก็ต่อเมื่อส่งเข้า CMDB ถูกต้อง มี guardrail ป้องกันไม่ให้เอา ID ชั่วคราวไปใช้จริง และยังมีขั้นตอนนำ ID ที่ยืนยันแล้วแต่ไม่ได้ใช้กลับมารีไซเคิลด้วย ตอนที่ได้ยินล่าสุด พวกเขายังอยู่เดือนที่ 18 ของโปรเจกต์ 6 เดือนในการย้าย local DB cache ไป Zookeeper
CodesInChaos: ปกติสาเหตุมาจาก ตัวสร้างเลขสุ่มเทียมที่มี seed ไม่พอ เรื่องสำคัญคือ UUID ถูกสร้างในแบ็กเอนด์หรือฟรอนต์เอนด์
ฝั่งฟรอนต์เอนด์เชื่อถือได้ยากโดยพื้นฐาน ไม่ว่าจะเพราะการชนกันแบบจงใจหรือเหตุผลอื่น ๆ จึงต้องมีการจัดการ collision ส่วนแบ็กเอนด์ทำให้เสถียรได้ ในอดีต VM เคยมีปัญหานี้ แต่ปัจจุบันควรจะแก้ไปแล้ว อย่างไรก็ดี ถ้า process ที่ถูก sandbox หนัก ๆ ไปใช้เส้นทางสุ่มสำรองที่ไม่ปลอดภัยก็ยังเจอได้ และการ fork process หรือ VM ก็อาจทำให้เกิด collision จากการคัดลอก state
kst: ทำให้นึกถึงข้อความตอนหนึ่งใน “Pro Git” <https://git-scm.com/book/en/v2>
เขายกตัวอย่างว่า ต่อให้มนุษย์ 6.5 พันล้านคนบนโลกสร้างโค้ดขนาดเท่าประวัติทั้งหมดของ Linux kernel ทุกวินาที แล้ว push เข้า Git repository เดียวขนาดมหึมา ก็ยังต้องใช้เวลาราว 2 ปี กว่าความน่าจะเป็นของ SHA-1 object collision จะถึง 50% เลยชอบสำนวนที่บอกว่า SHA-1 collision ตามธรรมชาตินั้นมีโอกาสน้อยกว่าที่สมาชิกทีมทุกคนจะตายในคืนเดียวกันจากการถูกหมาป่าจู่โจมโดยไม่เกี่ยวข้องกัน แม้ SHA-1 hash จะไม่ใช่เลขสุ่มและมี 160 บิต จึงไม่เหมือน UUIDv4 แต่ผมชอบอุปมาเรื่อง การถูกหมาป่าจู่โจมโดยไม่เกี่ยวข้องกัน
เป็นอุปมาประมาณว่า ต่อให้เดินรอบโลกที่เส้นศูนย์สูตรทุก 1 พันล้านปีหนึ่งก้าว และทุกครั้งที่ครบรอบหนึ่งรอบก็ตักน้ำออกจากมหาสมุทรแปซิฟิกหนึ่งหยด พอมหาสมุทรแห้งก็วางกระดาษหนึ่งแผ่น แล้วทำซ้ำจนกองกระดาษสูงถึงดวงอาทิตย์ เลขสามหลักแรกของตัวจับเวลา 52! วินาทีก็ยังไม่เปลี่ยน
e12e: มีการคุยที่เกี่ยวข้องอยู่ที่นี่: https://github.com/uuidjs/uuid/issues/546
ตัวอย่างเช่น มีการทดสอบ
crypto.getRandomValues()กับ googlebot แล้วพบว่ามันเป็นแบบ กำหนดแน่นอนadyavanapalli: เรื่องที่กำลังพูดถึงนี้หายากมาก ขนาดว่าความเป็นไปได้ที่โลกทั้งใบจะโดนดาวเคราะห์น้อยทำลายในตอนนี้ยังสูงกว่า
เคยได้ยินว่ามีผู้หญิงคนหนึ่งโดนอุกกาบาตจริงแต่รอดมาได้โดยบาดเจ็บที่ขา ถ้าเกิด UUID collision จริง ความเป็นไปได้สูงลิ่วคือมีบั๊กซอฟต์แวร์หรือคอมพิวเตอร์ผิดปกติ และอาจเป็นรังสีคอสมิกก็ได้ รังสีคอสมิกไปรบกวนหน่วยความจำหรือ CPU เกิดขึ้นบ่อยกว่าที่คนส่วนใหญ่คิด
juancn: เป็นไปได้ไหมว่าการ initialize ตัวสร้างเลขสุ่มแปลก ๆ หรือเอนโทรปีไม่พอ? ถ้าไม่ได้ปรับแต่งอะไร ปกติจะใช้
crypto.getRandomValues(rnds8)แต่getRandomValuesไม่ได้ระบุ ปริมาณเอนโทรปีขั้นต่ำ ไว้Geee: ตามการตีความกลศาสตร์ควอนตัมแบบหลายโลก จะต้องมีจักรวาลสาขาหนึ่งที่ UUID ทุกตัวเหมือนกันหมด จินตนาการได้เลยว่าคนในโลกนั้นจะคิดยังไง
mittermayr: เห็นด้วยเต็มที่ว่ามันฟังไม่สมเหตุสมผล แต่ถ้าจะเดา ผมคิดถึงความต่างว่าเมื่อก่อนสร้าง UUIDv4 บนมือถือของผู้ใช้แล้วส่งเข้า DB แต่ UUID ที่ชนกันวันนี้ถูกสร้างบนเซิร์ฟเวอร์ Ubuntu
ผมไม่แน่ใจว่า UUIDv4 สร้างอย่างไร หรือคุณลักษณะของเครื่องที่สร้างมีผลต่ออัลกอริทึมหรือไม่ แต่ความเปลี่ยนแปลงเดียวที่นึกออกคือ เมื่อก่อนสร้างบนอุปกรณ์ และเพิ่งย้ายมาสร้างบนเซิร์ฟเวอร์เมื่อไม่กี่เดือนก่อน
แต่ถ้าเป็นฝั่งเซิร์ฟเวอร์ โดยเฉพาะในปี 2026 ก็ไม่ควรเป็นแบบนั้น ในอดีต VM random seed เคยเป็นปัญหา แต่ทุกวันนี้ควรน้อยลงมาก ถึง UUID ฝั่งหนึ่งจะถูกสร้างมาแย่ แต่ถ้าอีกฝั่งสุ่มจริง โอกาสจะชนกันก็ยังต่ำมาก เพราะฉะนั้นน่าจะต้องมีปัญหาทั้งสองฝั่ง
dweez: ได้เวลากลับมาอ่านบทความสนุกชิ้นนี้อีกครั้ง: https://jasonfantl.com/posts/Universal-Unique-IDs/
ถ้าเปลี่ยนทั้งจักรวาลเป็นคอมพิวเตอร์ยักษ์แล้วสร้างแต่ UUID ไปจนถึงภาวะ heat death ของเอกภพ จะต้องใช้ ID space กี่บิต?
beejiu: อยากรู้ว่า UUID ถูกสร้างฝั่งไคลเอนต์หรือฝั่งเซิร์ฟเวอร์ ถ้าฝั่งไคลเอนต์อาจเป็นเพราะ crawler bot ก็ได้ เช่น Googlebot รัน JavaScript ด้วย “ความสุ่ม” แบบกำหนดแน่นอน
คำอธิบายแนวนี้สมเหตุสมผลกว่าการชนกันแบบสุ่มจริงอยู่หลายลำดับขั้น
merlindru: มีโอกาสสูงว่าเป็นปัญหาเรื่อง seed ถ้าพิสูจน์ได้ว่าไม่ใช่ คุณอาจดังขึ้นมานิดหน่อยก็ได้
erlkonig: ผมพูดกับทีมมาตลอดว่าถ้าข้อมูลมากพอ ค่าสุ่มก็มีวันชนกันได้ และตอนนั้นเราจะได้เห็นว่าซอฟต์แวร์แข็งแรงแค่ไหน
ถึงอย่างนั้นก็ยังมีนักพัฒนามากประสบการณ์ หัวหน้าทีม หรือ CIO จำนวนมากที่เชื่อว่ามันเป็นไปไม่ได้ แล้วไม่เขียนโค้ดรับมือกรณีนั้นเลย พอเป็นอย่างนี้ RNG ที่ไม่ดีก็พังระบบได้เร็วกว่าที่คาดมาก และอาจทำให้เสียหายพร้อมกันโดยไม่มีการตรวจจับหรือสร้างใหม่ ฟังดูคล้ายคนประเภทที่ไม่เช็กว่า
malloc()สำเร็จหรือไม่ ผมชอบถามกลับว่า “ถ้ามันเป็นไปไม่ได้จริง เราใช้บิตเยอะเกินไปหรือเปล่า?”leni536: มันไม่น่าใช่เรื่องบังเอิญ แต่มีบั๊กอยู่ที่ไหนสักแห่ง ดูคร่าว ๆ แล้วแพ็กเกจน่าจะเรียก
crypto.randomUUID()ของ JS runtime และตัวนี้ควร seed มาอย่างถูกต้องเสมอโอกาสที่ตัว runtime จะมีบั๊กก็ดูต่ำมาก แต่ก็ไม่แน่ อยากรู้ว่าใช้ JS runtime ตัวไหน
jbverschoor: สาเหตุที่ฟังดูเป็นไปได้ที่สุดคือแพ็กเกจ random generation ที่
uuidพึ่งพาอยู่เพิ่งถูก compromise จนทำให้เลข “สุ่ม” กลายเป็นสิ่งที่คาดเดาได้ ผลลัพธ์คืออาจมี supply chain attack ที่ทำให้โปรเจกต์ด้านการเข้ารหัส SSL และการเงินจำนวนมากเสี่ยงไปด้วยuuid/src/rng.tsที่เปลี่ยนเมื่อ 3 สัปดาห์ก่อน มีการเปลี่ยนอาร์เรย์สุ่มให้เป็นconstทำให้ทุกการเรียกใช้แชร์อาร์เรย์สุ่มชุดเดียวกันจากนั้นการเรียกถัดไปก็ไปอัปเดตรหัสสุ่มเดิม ดังนั้นถ้าคุณใช้มันสร้างอะไรสำคัญก็ขอให้โชคดี โค้ดเก่าใช้
slice()เพื่อทำสำเนาใหม่ อาจเป็นการเปลี่ยนโดยไม่ตั้งใจ แต่ผมไม่เข้าใจว่ามันหลุดมาได้ยังไง ทั้งที่ดูเหมือนแม้แต่เทสต์ที่สร้างเลขสุ่มสองตัวแล้วเช็กว่าไม่เหมือนกันก็น่าจะไม่ผ่านpif: ต่อให้มีแหล่งเอนโทรปีคุณภาพสูง ก็ไม่สามารถเปลี่ยนคำว่า “น่าจะเป็น” ให้กลายเป็น “รับประกันแน่นอน” ได้ ถ้าคุณต้องการค่าที่เดายาก ให้ไปหาวิธีทางคริปโต แต่ถ้าต้องการ ความไม่ซ้ำที่รับประกันได้ คุณต้องสร้างมันเอง
athrowaway3z: กฎคร่าว ๆ ง่าย ๆ คือให้คิดว่าคุณสามารถใส่ timestamp ลงไปใน ID นอกเหนือจากค่าที่สุ่มได้หรือไม่ ซึ่งส่วนใหญ่คำตอบคือได้ และ UUIDv7 ก็มักพอ
ถ้าคุณตรวจสอบปัญหานี้ลึกจนเขียนพิสูจน์ได้เองว่าการรั่วไหลของข้อมูลรับได้ไม่ได้ ก็ขอแสดงความยินดี ระบบนั้นน่าจะซับซ้อนและช้าพอที่จะใช้ strong cryptographic hash หรือถ้าขี้เกียจก็ใช้ UUIDv5 ได้
darqis: PostgreSQL 18 รองรับ uuidv7 แบบเนทีฟแล้ว และตั้งค่า default เป็น
uniqueกับuuid7()ได้เลยtumdum_: เป็นตัวสร้างเลขสุ่มเทียมที่มี seed แย่
serf: โอกาสระดับ 4.72 × 10²⁸ ต่อ 1 หรือประมาณ 47.3 octillion ต่อ 1 ถ้าเป็นเรื่องจริง ผมจะสงสัย race condition หรือความผิดพลาดง่าย ๆ อย่างอื่นก่อน มากกว่าจะไปซื้อลอตเตอรี่
evnix: ต่อให้ไม่พูดถึงคณิตศาสตร์ความน่าจะเป็น โลกจริงที่เราอยู่ก็ทำให้แม้แต่ hardware RNG ที่ดีที่สุดยังสุ่มน้อยกว่าที่คิดได้
ถ้าไม่ได้เป็นจุดที่ security สำคัญมาก ผมจะย้ายไปใช้พวก TSID หรือ uuidv7 เพื่อทำให้เรื่องแบบนี้แทบไม่เกิดในทางปฏิบัติ ดีกว่าการออกแบบโค้ด retry ให้ซับซ้อนเกินไป
jordiburgos: ขออย่าใช้
b6133fd6-70fe-4fe3-bed6-8ca8fc9386cdเลยนะ ผมเช็ก DB ตัวเองแล้ว มันถูกใช้ไปแล้ว16b55183-1697-496e-bc8a-854eb9aae0f3อยู่ และน่าจะมีอีก ถ้าทุกคนมาโพสต์รายการของตัวเองตรงนี้ เราน่าจะเช็กความซ้ำกันได้ไหม?pyuser583: อยากรู้ว่าทุกวันนี้ UUID แบบไหนเป็นตัวเลือกที่นิยมกว่า
smokel: ผมเคยโทษ compiler โทษรังสีคอสมิก โทษ quantum effect หรืออย่างน้อยก็โทษ kernel bug แปลก ๆ ก่อนจะมารู้สุดท้ายว่าตัวเองนี่แหละคือบั๊กอยู่หลายครั้ง
การชนกันใน 15,000 เรคอร์ด มันไม่น่าเป็นไปได้เกินไป ผมจะสงสัยสาเหตุอื่นก่อน เช่น การจัดการรายการซ้ำ คำขอที่ถูกส่งซ้ำ object ที่ถูกนำกลับมาใช้ใหม่ log ที่ทำให้เข้าใจผิด หรือการนำ identifier จาก code path อื่นกลับมาใช้ ถ้าแชร์โค้ดรอบ ๆ เพิ่มอีกนิด คนอื่นน่าจะช่วยดูได้
wazoox: เรื่องนี้ยังไม่เคยเกิดกับผม แต่เมื่อสองวันก่อนผมเพิ่งเจอสิ่งนี้ลึกเข้าไปใน codebase PHP ที่รันอยู่บน production: ฟังก์ชัน
createUUID()ที่เอาค่าmd5(uniqid('', true))มาตัดแล้วประกบเป็นหน้าตา UUIDไม่รู้เหมือนกันว่าทำไมความสยองแบบนี้ถึงยังไม่กัดจุดตายเรา
sedatk:
uuidjs/uuidมีคำเตือนว่าอาจสร้าง UUID ซ้ำได้บนไคลเอนต์ที่มี ตัวสร้างเลขสุ่มแบบกำหนดแน่นอน อย่าง Googlebotสำหรับแอปที่คาดว่า UUID ที่สร้างฝั่งไคลเอนต์จะต้องไม่ซ้ำเสมอ เรื่องนี้อาจเป็นปัญหา จึงควรมีวิธีตรวจหาค่าซ้ำและล้มเหลวอย่างสวยงาม หรือปิดการเขียนจากไคลเอนต์ Googlebot ไปเลย: https://github.com/uuidjs/uuid/commit/91805f665c38b691ac2cbd...
xyzzy123: เคยมีระบบกระจายตัวบน Linux ที่ผมทำ load test อยู่ล้มเหลวเพราะ UUID ซ้ำ
หลังจากสืบอยู่นานก็พบว่าเป็น kernel bug หรือพูดให้ชัดคือ race condition บนระบบหลายโปรเซสเซอร์ ถ้าสองโปรเซสอ่าน
/dev/randomพร้อมกันพอดี บางครั้งที่หายากมาก ระดับประมาณหนึ่งในล้าน จะได้ไบต์ชุดเดียวกันกลับมา ผมคงไปดูการ initialize RNG ก่อนbaq: เหมือน VM ที่รันอยู่ทำเอนโทรปีหายไปหมดเพราะ virtualization
glaslong: คงต้องไปซื้อโคมลาวาสักหน่อยแล้ว
0xfffafaCrash: อยากรู้ว่า UUID ถูกสร้างที่ฟรอนต์เอนด์หรือแบ็กเอนด์ ถ้าเป็นฟรอนต์เอนด์ ผมจะเดิมพันว่ามันไม่ใช่ปัญหาเอนโทรปี แต่เป็นการดัดแปลงโค้ดไคลเอนต์หรือคำขอเพื่อฉีด UUID ที่รู้อยู่แล้ว เข้ามา
latentframe: หนึ่งในคำพูดที่อันตรายที่สุดในงานวิศวกรรมคือ เป็นไปไม่ได้ในทางสถิติ เมื่อสเกลใหญ่พอ กรณีสุดโต่งจะไม่ใช่ทฤษฎีอีกต่อไป แต่เป็นเหตุการณ์ใน production
8organicbits: ปีที่แล้วผมเคยเขียนเรื่องนี้ไว้รวมถึง collision จริงและไลบรารีที่เกี่ยวข้อง: https://alexsci.com/blog/uuid-oops/
UUID จะมีความทนทานต่อการชนกันได้ก็ต่อเมื่อมีข้อจำกัดหลายอย่างที่ต้องปฏิบัติตามอย่างเคร่งครัด และกรณีนี้ก็ดูเหมือนมีแนวโน้มสูงว่าเป็นปัญหาที่ตัวสร้างเลขสุ่ม
nu11ptr: สุดท้ายก็เป็นปัญหา แหล่งเอนโทรปี นั่นแหละ เพราะงั้นผมเลยสร้างและ insert ในลูปเสมอ ถ้าเกิดชนกันก็จัดการได้อย่างสวยงาม
sbuttgereit: มันไม่ใช่ “เป็นไปไม่ได้ทางเทคนิค” มัน เป็นไปได้ทางเทคนิค มาก ๆ แค่ถ้ามีความสุ่มดีพอ โอกาสจะน้อยมาก ๆ เท่านั้น และ UUIDv4 ก็ไม่ได้มีอะไรที่ป้องกันไม่ให้มันสร้างค่าซ้ำได้ในเชิงเทคนิค
beardyw: อาจเป็นคำถามงี่เง่า แต่เราเอาวันที่ต่อท้ายเข้าไปสักหน่อยไม่ได้เหรอ อย่างน้อยเป็นวินาทีในรูปเลขฐานสิบหกก็ยังดี แค่เพิ่มไม่กี่ไบต์ก็น่าจะช่วยรับประกันได้ว่าสิ่งที่โอเควันนี้จะยังโอเคในอนาคต
mdavid626: ก็อาจมีคำอธิบายอื่นได้เหมือนกัน เช่น มีใครไปแก้ request ด้วยมือ หรือไปแก้ DB
radial_symmetry: ผมก็เคยเจอเรื่องแบบนี้ครั้งหนึ่งจนคิดว่าตัวเองกำลังจะบ้า แต่พอได้อ่านคอมเมนต์พวกนี้ก็โล่งใจขึ้น
NKosmatos: มันไม่ใช่ “เป็นไปไม่ได้ทางเทคนิค” ไม่ได้เป็นไปไม่ได้ แค่ ไม่น่าเป็นไปได้มาก ๆ เท่านั้น คงต้องไปซื้อลอตเตอรี่แล้วมั้ง
ทุกครั้งที่ใช้คำว่า “improbable” ผมจะนึกถึง https://hitchhikers.fandom.com/wiki/Infinite_Improbability_D...
sudb: ตอนนี้รู้สึกเป็นครั้งแรกว่าการเลือก CUID2 ในโปรเจกต์หนึ่งของผมเป็นความคิดที่ดีจริง ๆ: https://github.com/paralleldrive/cuid2