Sql-Server

SQL Server 中的 Uniqueidentifier 如何始終是全域唯一值?

  • October 17, 2016

根據有關 UniqueIdentifier 的 microsoft 文件,該值始終是全域唯一的,因為它基於網路時鐘和 CPU 時鐘時間,另一方面,相同的文件說

uniqueidentifier 列可能包含多次出現的單個 uniqueidentifier 值,除非還為該列指定了 UNIQUE 或 PRIMARY KEY 約束。

我無法得出唯一標識符(GUID)如何在全球範圍內唯一的結論,因為網路地址(Mac 地址)在兩個不同的網路上可以相同,GUID 如何在全球範圍內通過哪些組合是唯一的,以及為什麼微軟這麼說應該是主要或唯一約束,以確保我們始終擁有唯一的 UniqueIdeifer 值。

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

問題 #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 文件:

GUID 是一個 128 位整數(16 個字節),可以在需要唯一標識符的所有電腦和網路中使用。這樣的標識符被複製的機率非常低。

非常確定地,這個函式返回一個唯一的值——在相同或任何其他系統(網路或非網路)上的任何其他呼叫都不應該返回相同的值。

請注意,非 SQL Server 文件甚至沒有提到 MAC 地址。並且文件CoCreateGuid指向了生成的真正函式:UuidCreate。該函式的文件指出:

出於安全原因,通常希望防止網路上的乙太網地址在公司或組織之外可用。UuidCreate函式生成的UUID無法追溯到生成它的電腦的乙太網地址**。它也不能與在同一台電腦上創建的其他UUID關聯。如果您不需要此級別的安全性,您的應用程序可以使用UuidCreateSequential函式,該函式的行為與所有其他作業系統版本上的UuidCreate**函式完全相同。

這裡的含義是使用 MAC 地址(除非使用NEWSEQUENTIALID())。事實上,在 SQL Server 中通過生成一些 GUIDNEWID()表明它們是RFC 4122 版本 4 UUID,它們極有可能是唯一的。這裡有一個圖表,Random UUID probability of duplicates,它顯示了重複的可能性有多大。然而,即使是非常非常低的重複機率也不能保證唯一性。

所以…

無法保證新生成的 GUID/UUID 值是唯一的。而且,即使有保證,UNIQUEIDENTIFIER 數據類型仍然與實際唯一性無關(如 Brent 的回答所示)。唯一性,一個或多個(即數據,而不是數據類型)只能由唯一索引/約束強制執行。


相關資料:

因為 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;

沒有什麼可以阻止您這樣做 - 除非您指定有關強制唯一性的表的某些內容。

引用自:https://dba.stackexchange.com/questions/152414