我正在使用SQL Server 2000中的一个数据库,该数据库为每个使用与其绑定的应用程序的用户使用GUID。不知何故,两个用户最终获得了相同的GUID。我知道微软使用一种算法来生成随机GUID,该GUID引起碰撞的可能性极低,但是碰撞仍然可能吗?
我正在使用SQL Server 2000中的一个数据库,该数据库为每个使用与其绑定的应用程序的用户使用GUID。不知何故,两个用户最终获得了相同的GUID。我知道微软使用一种算法来生成随机GUID,该GUID引起碰撞的可能性极低,但是碰撞仍然可能吗?
Answers:
基本上没有 我认为有人在破坏您的数据库。根据所使用的GUID版本,该值是唯一的(对于版本1 GUID而言),或者是唯一且不可预测的(对于版本4 GUID而言)。SQL Server的NEWID()函数的实现似乎使用了128位随机数,因此不会发生冲突。
要产生1%的碰撞几率,您需要生成大约2,600,000,000,000,000,000 GUID。
基本上不可能!,天文机会很少。
但是...我是我所认识的世界上唯一一个曾经有过GUID菌落的人(是!)。
我敢肯定,这不是一个错误。
在运行于Pocket PC上的小型应用程序中,在操作结束时,必须发出具有生成的GUID的命令,这是怎么发生的。在服务器上执行后的命令,连同执行日期一起存储在服务器上的命令表中。有一天,当我进行调试时,我发出了模块命令(附加了新生成的GUID),但没有任何反应。我又做了一次(使用相同的guid,因为guid在操作开始时只生成了一次),然后又一无所获,最终试图找出为什么命令未执行的原因,我检查了命令表, 3周前插入了与当前GUID相同的GUID。不相信这一点,我从2周的备份中恢复了数据库,并且guid在那里。检查代码,毫无疑问,新生成的新guid。
编辑:有些因素可能会大大增加发生这种情况的可能性,该应用程序在PocketPC模拟器上运行,并且该模拟器具有保存状态功能,这意味着每次恢复状态时,本地时间也会恢复并且guid基于内部计时器。...而且紧凑框架的guid生成算法可能不如COM那样完整。
从理论上讲,它们是可能的,但如果有3.4E38个可能的数字,则如果您一年内创建数十万亿的GUID,则重复的几率为0.00000000006(来源)。
如果两个用户最终使用相同的GUID,我敢打赌程序中存在一个错误,该错误导致数据被复制或共享。
首先,让我们看一下两个GUID发生碰撞的机会。正如其他答案所指出的那样,由于生日悖论,它不是2 ^ 128(10 ^ 38)中的1,它不是,这意味着对于两个GUID发生冲突的可能性为50%,实际上是2 ^ 64中的1(10 ^ 19)小得多。但是,这仍然是一个非常大的数目,因此,假设您使用的是合理数量的GUID,发生碰撞的可能性很低。
还请注意,GUID不包含很多人似乎相信的时间戳或MAC地址。对于v1 GUID确实如此,但是现在使用v4 GUID,它只是一个伪随机数,这意味着发生碰撞的可能性可能更高,因为它们不再是时间和机器所独有的。
因此,基本上答案是肯定的,可能发生碰撞。但是它们极不可能。
编辑:固定说2 ^ 64
1 in 10^64 (10^19)
,我想应该是1 in 2^64 (10^19)
。我也很困惑您如何认为生日悖论仅适用于2个数字。我假设您查看了en.wikipedia.org/wiki/Birthday_paradox。该表显示了给定的重复概率,您需要多少个向导。从该表中,十分之一为18 ^的概率需要2.6 * 10 ^ 10 guid,而不是仅与两个GUID接近的概率。
两个随机GUID碰撞的机会(10 ^ 38中的1)比未检测到损坏的TCP / IP数据包的机会(10 ^ 10中的1)低。 http://wwwse.inf.tu-dresden.de/data/courses/SE1/SE1-2004-lec12.pdf,第11页。磁盘驱动器,CD驱动器等也是如此。
GUID在统计上是唯一的,并且您从数据库读取的数据在统计上仅是正确的。
在这种情况下,我认为奥卡姆(Occam)的剃须刀是一个很好的指南。发生GUID冲突的可能性极低。您更有可能是一个错误,或有人弄乱了您的数据。
参见Wikipedia的全球唯一标识符文章。有几种生成GUID的方法。显然,旧的(?)方式使用Mac地址,时间戳(单位短)和唯一的计数器(用于在同一台计算机上管理快速生成),因此几乎不可能复制它们。但是这些GUID被删除了,因为它们可以用来追踪用户...
我不确定Microsoft使用的新算法(文章说可以预测一系列GUID,看起来它们不再使用时间戳了吗?上面链接的Microsoft文章说了别的话...)。
现在,顾名思义,GUID经过精心设计,使其具有全球唯一性,因此,我将冒这种可能性,即可能性很小或非常非常低的风险。我会去别的地方。
两台具有具有重复MAC地址的以太网卡的Win95机器将在严格控制的条件下发出重复的GUIDS,例如,如果建筑物中的电源关闭并且它们都完全同时启动,则尤其如此。
我将以“我不是网络人士,因此我可能在后面说完全不连贯的句子”作为开头。
当我在伊利诺伊州立大学工作时,我们有两个在不同时间订购的Dell台式机。我们将第一个放入网络,但是当我们尝试将第二个放入网络时,我们开始收到疯狂的错误。经过大量的故障排除后,确定两台计算机都在生成相同的GUID(我不确定确切用于什么目的,但是这使它们在网络上均无法使用)。戴尔实际上将两台计算机都替换为有缺陷的计算机。
我知道人们喜欢一个很好的答案,即GUID是神奇的并且保证是唯一的,但是实际上,大多数GUID只是121位随机数(其中有7位浪费在格式化上)。如果您不喜欢使用大随机数,那么使用GUID也不适合。
仅出于咧嘴笑,请尝试以下脚本...(适用于SQL 2005,不确定2000)
declare @table table
(
column1 uniqueidentifier default (newid()),
column2 int,
column3 datetime default (getdate())
)
declare @counter int
set @counter = 1
while @counter <= 10000
begin
insert into @table (column2) values (@counter)
set @counter = @counter + 1
end
select * from @table
select * from @table t1 join @table t2 on t1.column1 = t2.column1 and t1.column2 != t2.column2
反复运行(耗时少于一秒钟)与第一次选择相比,即使在极短的时间间隔内也会产生相当大的范围。到目前为止,第二选择什么都没有产生。
如果通过诸如 NEWID()
SQL Server中函数之(尽管当然,正如其他答案所强调的那样)。他们没有指出的一件事是,如果在野外的浏览器中使用JavaScript生成GUID,实际上很可能会遇到冲突。RNG有时在不同的浏览器中不仅会出现问题,而且我还遇到了这样的问题:Google蜘蛛似乎会缓存类似功能的结果,并最终将相同的GUID反复传递给我们的系统。
有关更多详细信息,请参见此处的各种答案: