**通用唯一识别码**（英語：，缩写：**UUID**）是用于计算机体系中以识别信息的一个128位标识符。

UUID按照標準方法生成時，在實際應用中具有唯一性，且不依赖中央机构的注册和分配。UUID重复的概率接近零，可以忽略不计。

因此，所有人都可以自行建立和使用UUID，而且幾乎可以確定其不會與既有的識別碼重複。也因為如此，在不同地方產生的UUID可以使用於同一個資料庫或同一個頻道中，而且幾乎不可能重複。

UUID的應用相當普遍，許多計算平台都提供了對於生成和解析UUID的支援。

历史
--

1990年代， UUID 原本是用于阿波羅電腦的网络计算系统，后被用于开放软件基金会的分散式運算環境。分散式運算環境UUID的初始设计基于网络计算系统UUID，其设计受 Domain/OS 中定义和使用的（64位）唯一标识符的启发，这是一个也由 阿波羅電腦 设计的操作系统。后来，微軟視窗平台采用分散式運算環境设计作为全局唯一标识符（GUID）。 

2005年7月，RFC 4122 为 UUID 注册了一个 URN 命名空间，并制定了早期的规范。当 RFC 4122 作为互联网工程任务组标准发布时，国际电信联盟基于先前的标准和 RFC 4122 早期版本标准化了 UUID。

标准
--

UUID 由开放软件基金会标准化，作为分散式運算環境（DCE）的一部分。

UUID 被紀錄为 ISO/IEC 11578:1996 "Information technology – Open Systems Interconnection – Remote Procedure Call（RPC）" 和後來的 ITU-T Rec. X.667 | ISO / IEC 9834-8：2005 规范的一部份。

互联网工程任务组公布了标准 RFC 4122，技术上等同于 ITU-T Rec. X.667 | ISO/IEC 9834-8。

格式
--

在其规范的文本表示中，UUID 的 16 个 8 位字节表示为 32 个十六进制数字，由连字符 '-' 分隔成五组顯示，形式為「8-4-4-4-12」总共 36 个字符（32 个十六进制数字和 4 个连字符）。

例如：

`123e4567-e89b-12d3-a456-426655440000`
`xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`
四位数字 `M`表示 UUID 版本，数字 `N`的一至三个最高有效位表示 UUID 变体。在例子中，*M* 是 `1` 而且 *N* 是 `a`（`10xx2`），這意味着此 UUID 是「变体1」、「版本1」UUID；即基于时间的 DCE/RFC 4122 UUID。

规范的 `8-4-4-4-12` 格式字符串基于 UUID 的16个字节的"记录布局"：

UUID 记录结构| 名称 | 长度 （字节） | 长度（16进制数字码长） | 说明 |
| --- | --- | --- | --- |
| time\_low | 4 | 8 | 整数：低位 32 bits 时间 |
| time\_mid | 2 | 4 | 整数：中间位 16 bits 时间 |
| time\_hi\_and\_version | 2 | 4 | 最高有效位中的 4 bits"版本"，后面是高 12 bits 的时间 |
| clock\_seq\_hi\_and\_res clock\_seq\_low | 2 | 4 | 最高有效位为 1-3 bits"变体"，后跟13-15 bits 时钟序列 |
| node | 6 | 12 | 48 bits 节点 ID |

这些字段对应于「版本1」和「版本2」（基于时间的）UUID中的字段，但是「8-4-4-4-12」的表示適用於所有UUID，即使对于生成方式不同的UUID也是如此。

RFC 4122 第 3 节要求以小写形式生成字符，同时对输入不区分大小写，尽管一些常用的实现违反了此规则。

Microsoft GUID有時會以大括号表示：

`{123e4567-e89b-12d3-a456-426655440000}`
不应将此格式与"Windows注册表格式"相混淆，后者指的是大括号内的格式。

RFC 4122为UUID定义了统一资源名称（URN）命名空间。作为URN呈现的UUID如下：

`urn:uuid:123e4567-e89b-12d3-a456-426655440000`

编码
--

UUID 的二进制编码因系统而异。UUID的变体1是目前世界最常見的UUID，完全以大端序（big-endian）二进制存储与传输 UUID 。

例如，`00112233-4455-6677-8899-aabbccddeeff` 编码为字节 `00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff`。

其他系统，特别是 Microsoft 在其 COM/OLE 库中对 UUID 的字符串表示，使用混合端格式，其中 UUID 的前三组是小端序/小尾序（little-endian），后两组是 大端序/大尾序（big-endian）。

例如，`00112233-4455-6677-8899-aabbccddeeff` 编码为字节 `33 22 11 00 55 44 77 66 88 99 aa bb cc dd ee ff`。

变体
--

UUID的**变体**（variant）字段，占1到3位元。RFC 4122定义了4种变体：

* 变体 0 (最显著位为0，二進制為0xxx2，十六進制表示為016到716) 用于向后兼容已经过时的1988年开发的 Apollo 网络计算系统（NCS）1.5 UUID 格式。 前6字节是48比特时间戳（从1980年1月1日UTC开始的4微秒的滴答数），随后2个字节保留，再1个字节是地址族（address family，使用了0..13个情形），最后7个字节是主机ID。这类似于UUID的版本1.
* 变体 1 (二進制為10xx2，十六進制為816到b16)，定义在RFC 4122/DCE 1.1 UUIDs, 或"Leach–Salz" UUID。它是按照大端序作为二进制存储与传输。
* 变体 2 (二進制為110x2，十六進制為c16或d16)，RFC称"保留，微软公司向后兼容"。早期的Microsoft Windows平台的GUID使用该格式。和完全使用大端序的變體 1 不同，變體 2 其中一部份按照小端序作为二进制存储与传输。
* 形如111x2保留未使用。

目前的UUID規範使用變體1和2。在文字表示上，兩種變體只有代表變體的位元不同。上面的字段也定義了兩種變體之間的位元組轉換。前三個字段是無正負號的32和16位元數字，需要進行轉換，而後兩個字段是由未解釋的位元組組成，不需要進行轉換。這種轉換同樣適用於版本3、4和5，其中的規範字段與UUID的內容無關。

雖然一些重要的GUID名義上是變體2的UUID，例如元件對象模型（Component Object Model）IUnknown介面的識別碼，但是在微軟Windows軟體中所生成和使用的、被稱為「GUID」的許多識別碼是使用標準的變體1的RFC 4122/DCE 1.1大端序UUID。目前，Microsoft `guidgen`工具软件产生变体1的结果。某些微软文档称GUID与UUID是同义词，如同RFC 4122中表示UUID「也被稱作GUID」。這些文件表明了雖然「GUID」最初指代微軟所使用的其中一種UUID變體，但現在已經成為UUID的另一個名稱，含括變體1和2。

版本
--

对于「变体（variants）1」和「变体2」，标准中定义了五个版本（versions），并且在特定用例中某些版本可能比其他版本更合适。

版本由字符串中的 M 指示。

版本1的UUID是根据时间和节点ID（通常是MAC地址）生成；版本2的UUID是根据标识符（通常是组或用户ID）、时间和节点ID生成；版本3、版本5透過對命名空间（namespace）标识符和名称進行雜湊生成確定性的UUID；版本4的UUID則使用随机性或伪随机性生成。

### Nil UUID

Nil UUID是一个特例，值为 `00000000-0000-0000-0000-000000000000` ；也就是说，所有位都设置为 0。

### 版本1（日期时间和MAC地址）

版本1的UUID，是根据 60-bit 的时间戳和节点（生成UUID的计算机）的48-bit MAC地址而生成的。

时间戳的是这样计算的：自公曆首次於天主教會和教皇國以外的地方使用的日期，也就是协调世界时（UTC）1582年10月15日午夜算起，每經過100納秒時間戳加1。RFC 4122声明时间值在公元3400年左右算術溢位，取决于所使用的算法，代表此 60-bit 时间戳是有符号数量。但是，某些软件（如libuuid库）将时间戳视为无符号，把溢位時間推遲至公元5236年。ITU-T Rec. X.667所定義的溢位時間為公元3603年。

13-bit 或 14-bit「无统一」（uniquifying）时钟序列扩展了时间戳，以便处理处理器时钟不能足够快地前进的情况，或者每个节点有多个处理器和 UUID 生成器的情况。对于每个「版本1」UUID 对应于空间（节点）和时间（间隔和时钟序列）中的单个点，两个正确生成的「版本1」UUID 无意中相同的可能性实际上为零。由于时间和时钟序列总共74位，每个节点 id 可以生成 {\displaystyle 2^{74}}（{\displaystyle 1.8\times 10^{22}} 或 18 sextillion）個「版本1」UUID，每个节点 id 的最大平均速率为每秒 1630 亿。

与其他 UUID 版本相比，基于来自网卡的 MAC 地址的「版本1」和「版本2」UUID，部分依赖于由中央注册机构发布的标识符，即由 IEEE 发布给网络设备制造商的 MAC 地址的组织唯一标识符（OUI）。基于网卡MAC地址的「版本1」和「版本2」UUID 的唯一性还取决于网卡制造商正确地为其卡分配唯一的MAC地址，这与其他制造过程一样容易出错。此外，某些作業系統允許終端用戶自訂MAC地址，例如OpenWRT。

使用节点的网络MAC地址作为节点ID，代表可以透過版本1的UUID逆向找到创建它的计算机。透過在檔案中嵌入UUID，可以實現追蹤到創建或修改這些檔案的計算機。在定位 Melissa 病毒的创建者时就使用了这个隐私漏洞。

如果节点没有或不希望暴露MAC地址，RFC 4122 确实允许「版本1」（或2）UUID 中的 MAC 地址被随机的48位节点ID替换。在这种情况下，RFC要求节点ID的第一个八位字节的最低有效位应设置为1，这对应于MAC地址中的多播位，设置它是用于区分随机生成节点ID的UUID和基于来自网卡的MAC地址的UUID，网卡通常具有单播MAC地址。

### 版本2（日期时间和MAC地址，DCE安全版本）

RFC 4122 保留了版本2的UUID用於"DCE security"；但並没有提供任何细节。因此，许多 UUID 实现省略了「版本2」。但是，「版本2」UUID 的规范由 DCE 1.1 身份验证和安全服务规范提供。

「版本2」UUID 类似于「版本1」，除了时钟序列的最低有效8 bits 被"本地域（local domain）"号替换，并且时间戳的最低有效32 bits 由在指定本地域内有意义的整数标识符替换。在 POSIX 系统上，本地域号 0 和 1 分别用于用户 ID（UIDs）和组 ID（GIDs），其他本地域号用于站点定义。在非 POSIX 系统上，所有本地域号都是站点定义的。

在 UUID 中包含 40 位元的域或标识符（domain/identifier）是有代價的。一方面，40 位元允许每个节点ID有大约1个域或标识符的值。另一方面，由於时钟值被截断为28个最高有效位，有別於版本1中的60位元，版本2的UUID中的时钟也改成每429.49秒跳動（tick）一次，略多于7分钟，而不是版本1中的每100纳秒；并且，版本2的時鐘序列僅有6位元，版本1中則有14位元；每7分钟时钟周期内，每个节点、域或标识符只能生成64个唯一的UUID，而版本1的时钟序列值为16,384个。因此，版本2可能不适合用于以节点、域或标识符在约7秒以上1次的速率下生成 UUID 的情况。

### 版本3和版本5（基于命名空间名称）

「版本3」和「版本5」的 UUID 透過雜湊（hashing）命名空间标识符和名称生成。版本3使用 MD5 作为，版本5則使用 SHA1。

名称空间标识符本身就是一个 UUID。该规范提供了 UUID 用来表示命名空间为了统一资源定位符（URLs），完整域名、对象标识符和 X.500；但任何所需的UUID都可以用作命名空间指示符。

要确定与给定命名空间和名称对应的版本3的UUID，命名空间的 UUID 将转换为字节串，後面加上输入名称，然后用 MD5 进行，产生 128 位元。然后将六或七位替换为固定值，即 4 位元的版本號（例如"版本3"的 0011），以及 2 或 3 位元的 UUID 变体號（例如 10 代表RFC 4122的UUID，或 110 代表传统 Microsoft GUID）。由于预定了6到7位元，因此只有121或122位元用於維持 UUID 的唯一性。

版本5的UUID 和上面类似，但使用 SHA1 而不是 MD5。由于 SHA1 生成 160 位元的摘要，因此在替换版本號和变体號之前會把摘要截断为 128 位元。

版本3和版本5的UUID具有一個特性：相同名称空间和名称将映射到同一個UUID；然而，即使已知其中一項，也無法透過暴力搜索之外的方法從UUID逆向推導出另外一項。RFC 4122 推荐使用版本5（SHA1）而不是版本3（MD5），并建议不要使用任一版本的 UUID 作为安全凭证。

### 版本4（随机）

版本4的UUID是隨機生成的。与其他 UUID 一样，其中4位元用于代表「版本4」，2到3位元代表变体號（102 或 1102 分别用于变体 1 和 2）。因此，对于变体1（即大多数 UUID），隨機生成的版本4的UUID會保留6位元用於表示变体號和版本號，其餘122位元用於隨機生成，故版本4变体1的UUID共计有 {\displaystyle 2^{122}} 或{\displaystyle 5.3\times 10^{36}}（5.3 undecillion）个。版本4变体2的UUID（传统GUID）則為變體1的一半，因为可用的随机位少一个，变量消耗 3 位元。

一些伪随机数发生器缺少必要的熵来产生足够的伪随机数。例如，使用伪随机数生成器的 WinAPI GUID 生成器已被证明可生成遵循可预测模式的 UUID。 RFC 4122 建议"在各种主机上生成 UUID 的分布式应用程序必须愿意依赖所有主机上的随机数源。如果这不可行，则应使用名称空间变体。"

衝突
--

当多次生成相同的 UUID 并将其分配给不同的指示对象时，就会发生冲突。对于使用来自网卡的唯一MAC地址的标准版本1和2的UUID，只有当实施与标准不同时才可能发生冲突，无论是无意还是故意。

与使用MAC地址生成的版本1和版本2相比，使用随机生成的节点ID的版本1和版本2、基于散列的版本3和版本5，以及随机生成的版本4的UUID，即使实现上沒有问题也可能发生冲突，但可能性很小，通常可以忽略。可以基于对生日问题的分析来精确地计算该概率。

例如，如果要有50%的機率至少發生一次衝突，需要生成至少{\displaystyle 2.71\times 10^{18}}個版本4的UUID，计算如下：

{\displaystyle n\approx {\frac {1}{2}}+{\sqrt {{\frac {1}{4}}+2\times \ln(2)\times 2^{122}}}\approx 2.71\times 10^{18}}

这个数字相当于每秒产生 10 亿个 UUID 持續 85 年。每个 UUID 長度為 16 字节，这么多 UUID 的文件大小約為 45 艾字节（EB），比目前存在的最大数据库大很多倍，它们都在数百PB的数量级。

若要使發生衝突的機率為*p*，至少必須生成多少個版本4的UUID可由下式近似计算：

{\displaystyle {\sqrt {2\times 2^{122}\times \ln {\frac {1}{1-p}}}}}

因此，在 103 万亿个版本4 UUID 中找到重复的概率是 {\displaystyle {1 \over 1000000000}}（十亿分之一）。

使用
--

### 檔案系統

重要用途包括 ext2/ext3/ext4 文件系统用户空间工具（e2fsprogs 使用 util-linux 提供的 libuuid）、LUKS 加密分区、GNOME、KDE 和 Mac OS X，其中大部分源自 曹子德（Theodore Ts'o）的实现。

Solaris 中 UUID 的一种用途（使用開放軟體基金會的实现）是识别正在运行的操作系统实例，以便在内核崩溃的情况下将故障转储数据与故障管理事件配对。

分區標籤和分區UUID都儲存於超區塊中。兩者皆為檔案系統的一部份，而不是分區的一部份。例如，ext2-ext4包含UUID，而NTFS或FAT32則沒有。

超區塊是檔案系統的一部份，因此被完全包含在分區中，因此如果你執行`dd if=/dev/sda1 of=/dev/sdb1`，sda1和sdb1都會擁有相同的標籤和UUID。

### COM

Microsoft的组件对象模型（COM）中使用了几种GUID ：

* IID - 接口标识符；（在系统上注册的接口标识符存储在Windows注册表中的`[HKEY_CLASSES_ROOT\Interface]`）
* CLSID - 类标识符；（存储在`[HKEY_CLASSES_ROOT\CLSID]`）
* LIBID - 类型库标识符；（存储于`[HKEY_CLASSES_ROOT\TypeLib]`）
* CATID - 类别标识符；（它在一个类中的存在将其识别为属于某些类别类别，列於`[HKEY_CLASSES_ROOT\Component Categories]`）

### 作为数据库主键

UUID 通常用作数据库表中的唯一键。

Microsoft SQL Server 版本4 Transact-SQL 中的 NEWID 函数會返回标准随机版本4的UUID，而 NEWSEQUENTIALID 函数返回类似于 UUID 的 128 位标识符，这些 UUID 會依序遞增，直到下次系统重啟。

另一方面，尽管名称如此，但 Oracle Database SYS\_GUID 函数不会返回标准 GUID；相反，它根据主机标识符和进程或线程标识符返回一个16字节的 128 位 RAW 值，有点类似于 GUID。

PostgreSQL 包含一个 UUID 数据类型，并且可以通过使用模块中的函数生成大多数版本的UUID。

MySQL 提供了一个 UUID 函数，它生成标准的版本1 UUID。

当 UUID 用作主键时，版本3、4和5 UUID 的随机性以及 版本1和2 UUID 内的字段的排序可能会产生数据库定位或性能问题。例如，2002年 Jimmy Nilsson 报告说，当用作主键的版本4 UUID 被修改为包含基于系统时间的非随机后缀时，Microsoft SQL Server的性能显着提高。Nilsson 承认，这种所谓的"COMB"（组合时间和GUID）方法使UUID非标准并且更有可能被复制，但 Nilsson 仅要求在应用程序中的唯一性。透過重新排序和編碼版本1和版本2的UUID，將時間戳放在最前面，可以避免插入所造成的性能損失。

諸如Laravel這樣的部分網路框架支援「時間戳優先」的UUID，可以將UUID有效儲存於索引資料庫中。這種UUID是版本4格式的COMB UUID，但其中前48位元組成了一個時間戳，就像版本1的UUID一樣。其他基於COMB UUID概念的指定格式包括：

* **ULID**，其拋棄了用於表示版本4的4位元，並且預設使用base32編碼。
* UUID版本6到8是三種COMB UUID格式的正式提議。

参见
--

* 全局唯一标识符（GUID）

参考文献
----

1. ↑ . H2.  [21 March 2021]. （原始内容存档于2006-07-09）.
2. ↑  *ITU-T Recommendation X.667 （页面存档备份，存于）: Generation and registration of Universally Unique Identifiers (UUIDs) and their use as ASN.1 Object Identifier components*. Standard. October 2012.
3. ↑ . The Open Group. 1997  [2022-10-17]. （原始内容存档于2010-07-07）.
4. 1 2 3 . The Open Group. 1997  [2022-10-17]. （原始内容存档于2010-12-07）.
5. ↑ . ITU.int.  [2016-12-20]. （原始内容存档于2010-08-20）.
6. 1 2 3 4 5 6 7 8 9  Leach, P.; Mealling, M.; Salz, R.. A Universally Unique IDentifier (UUID) URN Namespace. Internet Engineering Task Force. 2005 [2017-01-17]. RFC 4122.
7. ↑ .  [2020-10-09]. （原始内容存档于2021-02-24）.
8. ↑ . Microsoft Developer Network. Microsoft.  [2020-10-09]. （原始内容存档于2019-02-13）.
9. 1 2 . Kernel.org.  [9 January 2017]. []
10. ↑ . www.itu.int. October 2012  [19 December 2020]. （原始内容存档于2022-10-17）.
11. ↑ . IEEE Standards Association.  [2022-10-17]. （原始内容存档于2018-03-05）.
12. ↑ . OpenWRT. 15 September 2021  [2022-10-17]. （原始内容存档于2022-10-18）.
13. ↑  Reiter, Luke.. ZDNet. 1999-04-02  [2017-01-16]. （原始内容存档于2012-10-21）.
14. ↑  Kuchling, A. M.. Python.org.  [23 January 2016]. （原始内容存档于2021-02-07）.
15. ↑  Jesus, Paulo; Baquero, Carlos; Almaeida, Paulo.  (PDF). Repositorium.Sdum.Uminho.pt.  [2022-10-17]. （原始内容存档 (PDF)于2022-10-17）.
16. ↑  Mathis, Frank H.. SIAM Review. June 1991, **33** (2): 265–270. CiteSeerX 10.1.1.5.5851 可免费查阅. ISSN 0036-1445. JSTOR 2031144. OCLC 37699182. doi:10.1137/1033051.
17. ↑ . Blogs.Oracle.com. Oracle.  [9 January 2017]. （原始内容存档于2016-06-29）.
18. ↑ . Windows Dev Center - Desktop app technologies. Microsoft.  [15 December 2015]. （原始内容存档于2017-07-06）. You reference an interface at run time with a globally unique interface identifier (IID). This IID, which is a specific instance of a globally unique identifier (GUID) supported by COM, allows a client to ask an object precisely whether it supports the semantics of the interface, without unnecessary overhead and without the confusion that could arise in a system from having multiple versions of the same interface with the same name.
19. ↑ . Microsoft Developer Network. Microsoft.  [15 December 2015]. （原始内容存档于2017-09-28）.
20. ↑ . Windows Dev Center - Desktop app technologies. Microsoft.  [15 December 2015]. （原始内容存档于2017-11-22）. A listing of the CATIDs and the human-readable names is stored in a well-known location in the registry.
21. ↑ . Microsoft Developer Network. Microsoft. 2015-08-08  [2017-01-14]. （原始内容存档于2010-06-06）.
22. ↑ . Oracle.  [2022-10-17]. （原始内容存档于2022-10-17）.
23. ↑ . PostgreSQL 9.4.10 Documentation. PostgreSQL Global Development Group. 13 February 2020  [2022-10-17]. （原始内容存档于2018-03-09）.
24. ↑ . PostgreSQL: Documentation: 9.6. PostgreSQL Global Development Group. 12 August 2021  [2022-10-17]. （原始内容存档于2018-03-09）.
25. ↑ . PostgreSQL: Documentation: 9.6. PostgreSQL Global Development Group. 12 August 2021  [2022-10-17]. （原始内容存档于2018-03-09）.
26. ↑ . . Oracle Corporation.  [2022-10-17]. （原始内容存档于2022-11-06）.
27. ↑  Nilsson, Jimmy.. InformIT. 2002-03-08  [2012-06-20]. （原始内容存档于2010-08-26）.
28. ↑ . Percona. 2014-12-19  [2021-02-10]. （原始内容存档于2020-11-29）.
29. ↑ . Laravel.com.  [2022-10-17]. （原始内容存档于2022-10-21）.
30. ↑  Cabrera, Italo Baeza.. Medium. 31 January 2020 （英语）.
31. ↑ . GitHub. ULID. 10 May 2021  [2022-10-17]. （原始内容存档于2022-12-22）.