SQL Server 中的 Uniqueidentifier 如何始终是全局唯一值?

Vis*_*lvi 8 sql-server uniqueidentifier sql-server-2012 uuid

根据关于 UniqueIdentifier 的 microsoft 文档,此值始终是全局唯一的,因为它基于网络时钟和 CPU 时钟时间,另一方面,相同的文档说

uniqueidentifier 列可能包含多次出现的单个 uniqueidentifier 值,除非还为该列指定了 UNIQUE 或 PRIMARY KEY 约束。

我无法得出唯一标识符(GUID)如何在全球范围内唯一的结论,因为网络地址(Mac 地址)在两个不同的网络上可以是相同的,GUID 如何在全球范围内使用哪些组合是唯一的,以及为什么微软在那里说应该是主要或唯一约束,以确保我们始终具有唯一的 UniqueIdeitifer 值。

https://technet.microsoft.com/en-us/library/ms190215(v=sql.105).aspx

Sol*_*zky 12

问题#1

根据有关UniqueIdentifier 的Microsoft 文档,该值在全局范围内始终是唯一的,因为它基于网络时钟和 CPU 时钟时间... (已添加强调)

这里的主要问题是您将两个不同的事物混淆为两个术语,它们指的是一件事:UNIQUEIDENTIFIER 和 GUID。

  • UNIQUEIDENTIFIER是一种数据类型。数据类型定义了它们(即这种类型的列和变量)可以包含的数据的性质(例如最小值/最大值等)和数据的某些行为(例如如何处理比较)。这种特定的数据类型仅包含GUID / UUID 值。但它不是数据,因此唯一性的概念不适用于它。“UniqueIdentifier”名称中的“Unique”一词并不是关于实际唯一性的承诺,甚至不是声明。

  • GUID / UUID 是可以存储为 的实际值UNIQUEIDENTIFIER,但也可以存储为VARBINARY/ BINARY(N)VARCHAR/ (N)CHAR,也许还有其他一些。虽然UNIQUEIDENTIFIER数据类型是存储这些值的最佳选择(在 SQL Server 中),但将值存储在其他类型中并不会使这些值或多或少具有唯一性。

问题#2

我无法得出唯一标识符(GUID)如何在全球范围内唯一的结论,因为网络地址(Mac 地址)在两个不同的网络上可以相同

这里的第二个问题是,您实际上接受了链接到的文档中的技术错误。我假设你指的是这个声明:

GUID 是唯一的二进制数;世界上没有其他计算机会生成该 GUID 值的副本。

该语句指的是像NEWID()T-SQL 和Guid.NewGuid().NET 中创建新 GUID/UUID 值的函数,以及它们始终生成唯一值的意图。然而,这不是现实:新生成的 GUID 不能保证是唯一的。正如您已经指出的,MAC 地址不一定是唯一的(它们甚至可以被欺骗;更多信息请参见下面的“相关信息”部分)。此外,来自其他 Microsoft 文档:

  • .NET Guid Structure状态的MSDN 页面(已添加强调):

    GUID 是一个 128 位整数(16 字节),可用于所有需要唯一标识符的计算机和网络。这样的标识符被复制的可能性非常低

  • .NET Guid.NewGuid()方法(用于生成新的 GUID/UUID 值)调用Win32Native.CoCreateGuid。该函数的文档说明(强调):

    以非常高的确定性,此函数返回一个唯一值——在相同或任何其他系统(联网与否)上的任何其他调用都不返回相同的值。

请注意,非 SQL Server 文档甚至没有提到 MAC 地址。并且文档CoCreateGuid指向执行生成的真实函数:UuidCreate。该功能的文档说明:

出于安全原因,通常需要防止网络上的以太网地址在公司或组织之外可用。所述UuidCreate函数生成一个UUID无法追踪到在其上生成的计算机的以太网地址。它也不能与在同一台计算机上创建的其他UUID相关联。如果您不需要此级别的安全性,您的应用程序可以使用UuidCreateSequential函数,该函数的行为与UuidCreate函数在所有其他版本的操作系统上的行为完全相同。

这里的含义是特别使用MAC 地址(除非使用NEWSEQUENTIALID())。事实上,在 SQL Server 中通过生成一些 GUIDNEWID()表明它们是RFC 4122,版本 4 UUID,它们极有可能是唯一的。这里有一个图表,随机 UUID 重复概率,它显示了重复的可能性有多大。然而,即使是非常非常低的重复概率也不能保证唯一性。

所以...

不能保证新生成的 GUID/UUID 值是唯一的。而且,即使有保证,UNIQUEIDENTIFIER 数据类型仍然与实际唯一性无关(如布伦特的回答所示)。唯一性,对于一或多(即数据,而不是数据类型)只能由唯一索引/约束强制执行。


相关信息:


Bre*_*zar 7

因为 UNIQUEIDENTIFIER 列可以存储您放入其中的任何 UNIQUEIDENTIFIER。拿这个代码:

CREATE TABLE dbo.Test (MyID UNIQUEIDENTIFIER);
INSERT INTO dbo.Test VALUES ('809A6AA3-E6D7-4099-8D6C-6B21ED732013');
INSERT INTO dbo.Test VALUES ('809A6AA3-E6D7-4099-8D6C-6B21ED732013');
INSERT INTO dbo.Test VALUES ('809A6AA3-E6D7-4099-8D6C-6B21ED732013');
SELECT * FROM dbo.Test;
Run Code Online (Sandbox Code Playgroud)

没有什么可以阻止您这样做 - 除非您指定有关强制唯一性的表的某些内容。