UUID là gì? Định dạng, các phiên bản và UUID vs GUID

UUID (universally unique identifier, mã định danh duy nhất toàn cục) là một số 128 bit dùng để gắn nhãn cho dữ liệu mà không cần hỏi máy chủ trung tâm để lấy ID trống tiếp theo. UUID thường được viết thành 36 ký tự: 32 chữ số thập lục phân chia thành năm nhóm theo mẫu 8-4-4-4-12, ví dụ f47ac10b-58cc-4372-a567-0e02b2c3d479. Định dạng này được quy định trong RFC 9562 (tháng 5/2024), thay thế RFC 4122.

Dùng thử miễn phí: Trình tạo UUID Miễn phí, không cần tài khoản.

Vậy UUID là gì trong thực tế và dùng để làm gì? Bất kỳ hệ thống nào cũng có thể tự tạo UUID, kể cả khi ngoại tuyến, mà vẫn gần như chắc chắn không ai khác tạo ra đúng giá trị đó. Vì vậy UUID được dùng phổ biến làm khóa cơ sở dữ liệu, tên tệp, ID yêu cầu và ID tin nhắn. Bài viết này giải thích định dạng, các phiên bản, xác suất trùng lặp thực tế, khác biệt giữa UUID và GUID, và cách chọn giữa v4 và v7. Để thử các ví dụ, hãy mở trình tạo UUID miễn phí trong một tab khác.

UUID là gì và gồm những phần nào? Định dạng 8-4-4-4-12

128 bit tương ứng 16 byte. Mỗi byte là hai chữ số thập lục phân, tổng cộng 32 chữ số, thêm bốn dấu gạch nối thành 36 ký tự. Hai vị trí có ý nghĩa cố định:

f47ac10b-58cc-4372-a567-0e02b2c3d479
              ^    ^
              |    +-- chữ số thứ 17 "a": variant (8, 9, a hoặc b = RFC 9562)
              +------- chữ số thứ 13 "4": phiên bản 4 (ngẫu nhiên)

Vì 6 bit này cố định, một UUID ngẫu nhiên phiên bản 4 có 128 − 6 = 122 bit ngẫu nhiên. Các chữ cái thập lục phân có thể viết hoa, viết thường hoặc lẫn lộn, nên F47AC10B-… và f47ac10b-… là cùng một UUID; viết thường là quy ước phổ biến nhất.

Các phiên bản UUID: từ v1 đến v8, nil và max

RFC 9562 định nghĩa tám phiên bản và hai giá trị đặc biệt:

Phiên bản Cách tạo Công dụng thường gặp
v1 Dấu thời gian 60 bit (bước 100 ns tính từ năm 1582) + clock sequence + ID nút, thường là địa chỉ MAC Hệ thống cũ
v2 DCE Security, không được mô tả chi tiết trong RFC Hiếm khi dùng
v3 Băm MD5 của UUID namespace và một tên ID lặp lại được (nên dùng v5)
v4 122 bit ngẫu nhiên Lựa chọn mặc định
v5 Băm SHA-1 của UUID namespace và một tên ID lặp lại được từ tên
v6 Các trường của v1, sắp xếp lại để dấu thời gian có thể sắp thứ tự Nâng cấp hệ thống v1
v7 Dấu thời gian Unix 48 bit tính bằng mili giây + bit ngẫu nhiên Khóa cơ sở dữ liệu, ID sắp xếp được
v8 Bố cục tùy chỉnh; chỉ version và variant là cố định Định dạng riêng của nhà cung cấp
Nil 00000000-0000-0000-0000-000000000000 Giá trị giữ chỗ "không có giá trị"
Max ffffffff-ffff-ffff-ffff-ffffffffffff Giá trị canh gác hoặc cận trên

Các phiên bản dựa trên tên có tính tất định. Namespace DNS với tên example.com luôn cho ra UUID v5 cfbff0d1-9375-5685-968c-48ce8b15ae17, trên mọi máy và trong mọi ngôn ngữ lập trình. Hãy dùng chúng khi cùng một đầu vào phải luôn ánh xạ tới cùng một ID.

UUID phiên bản 7 đặt thời gian lên đầu. Ví dụ này được tạo lúc 12:00:00 UTC ngày 24/09/2026, tức 1.790.251.200.000 mili giây sau mốc Unix epoch, hay 0x01a0d3496e00 ở hệ thập lục phân:

01a0d349-6e00-7c3f-9d21-4b6e8a1f0c57
^^^^^^^^^^^^^ ^    ^
|             |    +-- chữ số variant "9"
|             +------- phiên bản 7
+--------------------- dấu thời gian 48 bit (ms)

74 bit còn lại là ngẫu nhiên (hoặc một phần là bộ đếm, tùy thư viện).

UUID có duy nhất không? Xác suất trùng lặp của v4

UUID không được đảm bảo duy nhất, mà chỉ duy nhất với xác suất cực kỳ cao. Với 122 bit ngẫu nhiên, có 2^122 ≈ 5,3 × 10^36 giá trị v4 khả dĩ. Phép xấp xỉ nghịch lý ngày sinh cho ra số lượng UUID n cần tạo để có 50% khả năng ít nhất hai giá trị trùng nhau:

n ≈ √(2 · ln 2 · 2^122) ≈ 2,71 × 10^18

Tức là khoảng 2,71 tỷ tỷ UUID. Nếu tạo một tỷ UUID mỗi giây, bạn cần khoảng 86 năm mới đạt con số đó. Với khối lượng thực tế, rủi ro là không đáng kể:

Số UUID v4 đã tạo Xác suất xảy ra trùng lặp
1 tỷ (10^9) khoảng 9,4 × 10^-20
1 nghìn tỷ (10^12) khoảng 9,4 × 10^-14
103 nghìn tỷ (1,03 × 10^14) khoảng 1 phần 1 tỷ
2,71 × 10^18 khoảng 50%

Các con số này giả định bộ sinh số ngẫu nhiên tốt. Trên thực tế, trùng lặp thường do lỗi: bộ sinh được khởi tạo kém, máy ảo nhân bản dùng lại cùng trạng thái, hoặc mã nguồn sao chép một ID thay vì tạo ID mới. Vì vậy, ràng buộc duy nhất (unique constraint) trong cơ sở dữ liệu vẫn rất đáng có.

UUID vs GUID: khác nhau thế nào?

Trên thực tế là không khác. GUID (globally unique identifier) là tên Microsoft đặt cho cùng giá trị 128 bit đó, được dùng trong Windows, COM, .NET và SQL Server. Ví dụ, Guid.NewGuid() của .NET tạo ra một UUID phiên bản 4 bình thường. Khác biệt nằm ở cách hiển thị và lưu trữ:

Dạng văn bản:    f47ac10b-58cc-4372-a567-0e02b2c3d479
Thứ tự RFC:      f4 7a c1 0b | 58 cc | 43 72 | a5 67 0e 02 b2 c3 d4 79
Microsoft:       0b c1 7a f4 | cc 58 | 72 43 | a5 67 0e 02 b2 c3 d4 79

Văn bản giống hệt nhau; chỉ 16 byte thô là khác. Nếu sao chép GUID nhị phân giữa một hệ thống Microsoft và một hệ thống dùng thứ tự RFC, giá trị sẽ bị xáo trộn. Hãy chuyển đổi qua dạng văn bản, hoặc từ .NET 8 trở đi dùng ToByteArray(bigEndian: true). Microsoft mô tả các nhóm bị đảo trong tài liệu Guid.ToByteArray.

Vậy "UUID vs GUID" chỉ là chuyện tên gọi, không phải lựa chọn bạn cần đưa ra.

UUID v4 hay v7 làm khóa chính?

Cả hai đều là UUID 128 bit, nhưng hoạt động rất khác nhau trong chỉ mục.

v7 còn cho phép sắp xếp theo ID để có thứ tự tạo, và đọc được thời điểm tạo ngay trong ID. Đó cũng là nhược điểm: ai thấy một ID v7 đều biết bản ghi được tạo lúc nào, chính xác đến mili giây. Hãy dùng v4 cho định danh công khai cần giữ kín thời điểm, và v7 cho khóa nội bộ trong các bảng lớn, ghi nhiều.

Cách lưu UUID hiệu quả

Hãy lưu 16 byte, không lưu chuỗi 36 ký tự. Một cột văn bản chiếm ít nhất 36 byte cho mỗi giá trị, hơn gấp đôi, và mọi chỉ mục chứa khóa đó cũng phình theo.

Chỉ chuyển sang dạng văn bản ở rìa hệ thống, như API và log.

Cách tạo UUID trong code

Hầu hết ngôn ngữ đều có sẵn trình tạo:

import uuid
uuid.uuid4()                                   # random v4
uuid.uuid7()                                   # v7, Python 3.14+
uuid.uuid5(uuid.NAMESPACE_DNS, "example.com")  # cfbff0d1-9375-5685-968c-48ce8b15ae17
crypto.randomUUID(); // v4, in browsers (HTTPS pages) and Node.js
SELECT gen_random_uuid();  -- v4, built in since PostgreSQL 13
SELECT uuidv7();           -- v7, PostgreSQL 18+
Guid.NewGuid();         // v4
Guid.CreateVersion7();  // v7, .NET 9+

crypto.randomUUID() được mô tả trên MDN. Trong trình duyệt, hàm này chỉ hoạt động trên trang bảo mật (HTTPS).

Cách kiểm tra UUID bằng regex

Mẫu này chấp nhận dạng chuẩn của các phiên bản 1–8 với variant chuẩn (dùng chế độ không phân biệt hoa thường):

^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$

[1-8] kiểm tra chữ số phiên bản, còn [89ab] kiểm tra variant. Hãy thêm các bước kiểm tra riêng nếu bạn muốn chấp nhận cả UUID nil và max, dấu ngoặc nhọn hoặc tiền tố urn:uuid:.

UUID không phải là bí mật

UUID dùng để định danh, không dùng để bảo vệ. RFC 9562 nêu rõ các triển khai không nên cho rằng UUID khó đoán và không được dùng UUID làm cơ chế bảo mật. v1 để lộ thời điểm tạo và, theo truyền thống, địa chỉ MAC của máy tạo ra nó; v7 để lộ thời điểm tạo. Ngay cả v4 từ bộ sinh an toàn cũng không được thiết kế để làm token đặt lại mật khẩu hay khóa API. Với những mục đích đó, hãy dùng token ngẫu nhiên riêng, chẳng hạn từ trình tạo token, và vẫn kiểm tra quyền truy cập ở mỗi yêu cầu.

Các lựa chọn thay thế UUID

ULID là lựa chọn thay thế phổ biến với mục tiêu tương tự: 128 bit, dấu thời gian 48 bit tính bằng mili giây và 80 bit ngẫu nhiên, viết thành 26 ký tự Crockford Base32 để có thể sắp xếp như văn bản. Nếu bạn cần định dạng này, trình tạo ULID có thể tạo, giải mã ULID và chuyển chúng sang UUID. Với dự án mới, UUID v7 mang lại cùng khả năng sắp xếp theo thời gian mà vẫn giữ định dạng UUID chuẩn được cơ sở dữ liệu hỗ trợ sẵn.

Tạo và kiểm tra UUID trực tuyến

Trình tạo UUID miễn phí chạy hoàn toàn trong trình duyệt của bạn. Công cụ tạo UUID v1, v3, v4, v5 và v7 cùng các giá trị nil và max, tối đa 500 cái mỗi lần. Bạn có thể chọn chữ thường, chữ hoa hoặc dấu ngoặc nhọn, bỏ dấu gạch nối, phân tách danh sách bằng dòng mới, dấu phẩy, khoảng trắng hoặc dưới dạng mảng JSON, rồi sao chép hoặc tải về dưới dạng .txt hay .json. Với v3 và v5, hãy chọn namespace DNS, URL, OID hoặc X.500, hoặc dán namespace của riêng bạn.

Trình kiểm tra tích hợp chấp nhận dạng chuẩn, dạng có ngoặc nhọn, urn:uuid: và dạng không có gạch nối, rồi hiển thị phiên bản, variant và dạng chuẩn. Nó giải mã dấu thời gian của UUID v1 và v7, cùng clock sequence và nút của v1. Một vài giới hạn: công cụ không tạo v6 hay v8, v1 dùng nút ngẫu nhiên thay cho địa chỉ MAC của bạn, và các ID v7 tạo trong cùng một mili giây không được đảm bảo theo đúng thứ tự tạo, vì các bit sau dấu thời gian là ngẫu nhiên chứ không phải bộ đếm.

Câu hỏi thường gặp

UUID có giống GUID không?

Có. GUID là tên Microsoft đặt cho UUID. Giá trị và định dạng văn bản giống nhau; công cụ của Microsoft thường hiển thị GUID bằng chữ in hoa trong ngoặc nhọn, và một số API của Microsoft lưu ba trường đầu theo thứ tự little-endian ở dạng nhị phân.

Hai UUID có thể trùng nhau không?

Về lý thuyết là có, trên thực tế gần như không. Với v4, bạn cần khoảng 2,71 × 10^18 UUID mới có 50% khả năng xuất hiện một bản trùng. Trùng lặp thật thường do lỗi phần mềm hoặc bộ sinh số ngẫu nhiên hỏng, vì vậy hãy giữ ràng buộc duy nhất trên các cột khóa.

Nên dùng UUID v4 hay v7?

Dùng v7 cho khóa chính trong các bảng có nhiều thao tác chèn, vì ID theo thứ tự thời gian giữ chỉ mục gọn và sắp xếp theo thời điểm tạo. Dùng v4 khi ID được công khai và không nên để lộ thời điểm bản ghi được tạo.

UUID dài bao nhiêu?

UUID có 128 bit, tức 16 byte. Dạng văn bản chuẩn dài 36 ký tự: 32 chữ số thập lục phân và 4 dấu gạch nối. Bỏ gạch nối thì còn 32 ký tự, thêm ngoặc nhọn thì thành 38.

Dùng UUID trong URL có an toàn không?

Có thể hiển thị UUID, nhưng nó không phải cơ chế kiểm soát truy cập. Một UUID v4 ngẫu nhiên khó đoán, nhưng vẫn có thể lộ qua log, lịch sử trình duyệt hoặc header Referer, còn v1 và v7 để lộ thời điểm tạo. Luôn kiểm tra xem người dùng có quyền truy cập tài nguyên hay không.

Dùng thử miễn phí: Trình tạo UUID Miễn phí, không cần tài khoản.