Sự cố va chạm UUID v4: Khi "bất khả thi" lại xảy ra trên hệ thống thực tế
Một nhà phát triển đã giật mình khi nhận được cảnh báo trùng lặp khóa chính từ UUID v4 trong cơ sở dữ liệu chỉ chứa 15.000 bản ghi. Mặc dù xác suất thống kê của sự cố này gần như bằng không, các chuyên gia đã phân tích các nguyên nhân tiềm năng, từ lỗi di chuyển dữ liệu cho đến việc thư viện sinh số ngẫu nhiên bị giảm độ bảo mật.
Một lập trình viên vừa chia sẻ câu chuyện gây sửng sốt trên diễn đàn công nghệ: hệ thống của họ vừa ghi nhận một vụ va chạm (collision) thực sự đối với UUID phiên bản 4.
Đây là sự kiện được coi là "bất khả thi" về mặt thống kê, nhưng nó đã xảy ra ngay trên máy chủ của họ.
Sự cố hy hữu
Sáng nay, cơ sở dữ liệu của đội phát triển đã gửi ra cảnh báo lỗi trùng lặp khóa chính (duplicate key error). Bản ghi gốc được tạo vào khoảng một năm trước (năm 2025), và hệ thống vừa chèn một tài liệu mới với UUID v4 được sinh ra hoàn toàn độc lập trong ngày hôm nay.
Vấn đề nằm ở chỗ: hai bản ghi này sở hữu cùng một chuỗi định danh: b6133fd6-70fe-4fe3-bed6-8ca8fc9386cd.
Đội ngũ phát triển sử dụng thư viện uuid phổ biến trên NPM với đoạn mã cực kỳ đơn giản: gọi hàm uuidv4() và chèn vào cơ sở dữ liệu. Với chỉ khoảng 15.000 bản ghi, xác suất để một va chạm như vậy xảy ra gần như bằng 0. Vậy nguyên nhân do đâu?
Phân tích nguyên nhân
Cộng đồng lập trình viên đã nhanh chóng đưa ra các giả thuyết kỹ thuật để giải mã bí ẩn này, sắp xếp theo mức độ khả thi:
1. Lỗi nhập liệu hoặc di chuyển dữ liệu (Khả năng cao nhất)
Trong 99% các trường hợp báo cáo "UUID trùng lặp", nguyên nhân thực chất không phải do thuật toán sinh số ngẫu nhiên. Thường là do ai đó đã vô tình tải lại một bản sao lưu (backup), chạy một kịch bản gieo hạt (seed script), hoặc nhập dữ liệu từ môi trường khác vào hệ thống. Việc kiểm tra lịch sử git, các thao tác của đội ngũ vận hành (Ops) là bước đầu tiên cần làm.
2. Lỗi logic thử lại (Retry Logic)
Có thể ứng dụng gặp lỗi ràng buộc (constraint violation) khi chèn, sau đó tự động thử lại (retry) nhưng vẫn sử dụng biến UUID cũ trong phạm vi đó thay vì sinh một UUID mới. Điều này thường xảy ra khi đoạn mã sinh UUID nằm ngoài khối lệnh xử lý thử lại.
3. Thuật toán giả lập ngẫu nhiên yếu (Math.random fallback)
Một số phiên bản cũ của thư viện uuid trong các môi trường đóng gói (bundler) cụ thể có thể quay lại sử dụng Math.random() thay vì API an toàn crypto.getRandomValues(). Trong khi crypto sử dụng entropy ngẫu nhiên thực sự từ hệ điều hành, Math.random() là giả lập ngẫu nhiên (PRNG) và có thể tạo ra các mẫu lặp lại hoặc dễ dự đoán hơn, đặc biệt khi khởi tạo seed kém.
4. Lỗi fork tiến trình (Process Fork)
Nếu bộ tạo UUID chạy trong một tiến trình con (child process) được sao chép từ tiến trình cha đã từng sử dụng bộ tạo số giả ngẫu nhiên (PRNG), trạng thái entropy có thể bị sao chép nguyên bản sang tiến trình con. Điều này hiếm gặp trong Node.js hiện đại nhưng từng là vấn đề trong các hệ thống cũ.
Bài học kinh nghiệm
Nếu sau khi kiểm tra tất cả các yếu tố trên mà vẫn xác định được hai UUID này được sinh ra độc lập thông qua crypto.getRandomValues cách nhau một năm, chủ nhân của bài đăng đùa vui rằng người đó nên ra mua ngay một tờ vé số dự thưởng.
Tuy nhiên, với đặc thù kỹ thuật, nguyên nhân gần như chắc chắn nằm ở cách dữ liệu được quản lý hoặc cách thư viện được cấu hình, chứ không phải do vũ trụ "đùa bỡn" với thuật toán ngẫu nhiên.
Đối với các nhà phát triển, đây là lời nhắc nhở về tầm quan trọng của việc kiểm tra ràng buộc dữ liệu (constraint check) và thận trọng khi thao tác với các bản sao lưu cơ sở dữ liệu.
Bài viết liên quan
Phần mềm
Lo ngại về Bun: Liệu sự suy giảm của Claude Code có phải là điềm báo cho tương lai của runtime này?
04 tháng 5, 2026

Phần mềm
Google phát hành Chrome 148, vá 127 lỗ hổng bảo mật bao gồm các lỗi nghiêm trọng
07 tháng 5, 2026

Phần mềm
Tấn công chuỗi cung ứng WordPress: Kẻ tấn công mua 30 plugin trên Flippa và cài cửa sau
06 tháng 5, 2026
