我正在使用SQL Server 2000中的一个数据库,该数据库为每个使用它所绑定的应用程序的用户使用GUID。不知何故,两个用户最终得到了相同的GUID。我知道微软使用一种算法来生成一个随机GUID,这个GUID极有可能造成冲突,但仍然可能发生碰撞吗?
答案 0 :(得分:121)
基本上没有。我觉得有人跟你的数据库混在一起。根据您使用的版本GUID,值是唯一的(对于版本1 GUID之类的东西),或者是唯一的和不可预测的(对于版本4 GUID之类的东西)。 SQL Server的NEWID()函数实现似乎使用了128位随机数,因此您不会发生冲突。
对于1%的碰撞几率,您需要生成约2,600,000,000,000,000,000个GUID。
答案 1 :(得分:92)
基本上他们是不可能的!,机会天文数字低。
但是......我是世界上唯一一个我所知道的人,曾经有一个GUID colision (是的!)。
我很确定,而且这不是一个错误。
如何实现,在Pocket PC上运行的小型应用程序中,在操作结束时,必须发出具有生成的GUID的命令。在服务器上执行该命令后,该命令与执行日期一起存储在服务器上的命令表中。有一天,当我调试时,我发出了模块命令(附加了新生成的GUID),没有任何反应。我再次做了(使用相同的guid,因为guid仅在操作开始时生成一次),并且再次没有,最后试图找出命令未执行的原因,我检查了命令表,和3周前插入的当前GUID相同。不相信这一点,我从2周的备份中恢复了数据库,并且guid就在那里。检查代码,新的guid新生成毫无疑问。 Pow guid碰撞,只发生过一次,但我真的希望我能在乐透中获胜,机会更大:)。
编辑:有一些因素可能会大大增加发生这种情况的机会,应用程序在PocketPC模拟器上运行,并且模拟器具有保存状态功能,这意味着每次状态恢复时本地时间也恢复了guid是基于内部计时器...也紧凑框架的guid生成算法可能不如例如COM ... ...
答案 2 :(得分:28)
它们在理论上是可行的,但是对于3.4E38可能的数字,如果你在一年内创建了数万亿的GUID,那么一个副本的可能性是0.00000000006(Source)。
如果两个用户最终使用相同的GUID,我会打赌程序中存在导致数据被复制或共享的错误。
答案 3 :(得分:19)
首先让我们看看两个GUID发生冲突的可能性。正如其他答案所述,它不是因为birthday paradox而在1 ^ 2 128(10 ^ 38)中,这意味着对于两个GUID碰撞的概率为50%,实际上是2 ^ 64 (10 ^ 19)这个要小得多。但是,这仍然是一个非常大的数字,因此假设您使用合理数量的GUID的冲突概率很低。
另请注意,GUID不包含时间戳或MAC地址,因为许多人似乎也相信。 v1 GUID确实如此,now v4 GUIDs are used, which are simply a pseudo-random number这意味着碰撞的可能性更高,因为它们不再是时间和机器所独有的。
所以基本上答案是肯定的,碰撞是可能的。但他们极不可能。
编辑:固定为2 ^ 64
答案 4 :(得分:17)
两个随机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在统计上是唯一的,您从数据库中读取的数据仅在统计上是正确的。
答案 5 :(得分:13)
在这种情况下,我会认为Occam's razor是一个很好的指南。你发生GUID冲突的可能性极小。你很可能有一个错误,或者有人弄乱你的数据。
答案 6 :(得分:11)
请参阅维基百科的Globally Unique Identifier文章。有几种方法可以生成GUID。显然旧的(?)方式使用Mac地址,时间戳到一个非常短的单位和一个独特的计数器(在同一台计算机上管理快速生成),所以使它们复制几乎是不可能的。但是这些GUID被删除了,因为它们可以用来追踪用户......
我不确定微软使用的新算法(文章说可以预测一系列GUID,看起来他们不再使用时间戳了?上面链接的微软文章说了别的......)。
现在,GUID经过精心设计,按名称,全球独一无二,因此我将冒险这是不可能的,或者概率非常非常低。我会去其他地方看看。
答案 7 :(得分:9)
两台具有重复MAC地址的以太网卡的Win95机器将在严格控制的情况下发出重复的GUID,特别是例如,如果建筑物中的电源断电并且它们都在同一时间启动。
答案 8 :(得分:4)
我知道人们喜欢感觉良好的答案,GUID是神奇的并且保证是唯一的,但实际上,大多数GUID只是121位随机数(格式化时浪费了7位)。如果您觉得使用大型随机数感觉不舒服,那么使用GUID会感觉不舒服。
答案 9 :(得分:3)
用于生成GUID的代码是否有错误?是的,当然可以。但答案与编译器错误的答案相同 - 你自己的代码更有可能是错误的数量级,所以请先查看。
答案 10 :(得分:2)
当然可能......可能吗?不太可能,但有可能。
请记住,同一台机器正在生成每个GUID(服务器),因此很多基于机器特定信息的“随机性”都会丢失。
答案 11 :(得分:2)
有一个公式可以估计生成多少个大小为 S 的值以使它们中的两个值以概率 P 发生碰撞。
变量:
要发生碰撞,您必须在周围生成:
或者在 Python 中:
from math import sqrt, log
def how_many(bits, probability):
return 2 ** ((bits + 1) / 2) * sqrt(-log(1 - probability))
对于 GUID(128 位),要获得概率为 1% (0.01) 的碰撞, 你需要:
In [2]: how_many(bits=128, probability=0.01)
Out[2]: 2.6153210405530885e+18
...大约 2.6 * 10^18 个 GUID(即 42 艾字节的 GUID)。
请注意,此概率增长迅速。与位数无关,对于 99.99% 的概率,您只需要比 1% 多 30 倍的 GUID!
In [3]: how_many(bits=128, probability=0.9999)
Out[3]: 7.91721721556706e+19
相同的数字,但对于 int64 数据类型:
In [4]: how_many(bits=64, probability=0.01)
Out[4]: 608926881
In [5]: how_many(bits=64, probability=0.9999)
Out[5]: 18433707802
对于 1% 的碰撞概率,您需要 5 GB 的 int64-s。仍然很多,但与 GUID 相比,这是一个更容易理解的数字。
这就是所谓的 birthday problem - 在这篇维基百科文章中,您可以找到比这更精确的估计公式。
答案 12 :(得分:1)
只是为了咧嘴笑,请尝试以下脚本...(适用于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
重复运行(花费不到一秒),从第一次选择开始产生相当宽的范围,即使是非常短的时间间隔。到目前为止,第二个选择还没有产生任何东西。
答案 13 :(得分:0)
当然有可能,甚至可能。这并不是每个GUID都在可能的数字空间的随机部分。如果两个线程试图同时生成一个线程,除了某种带有信号量的集中式GUID函数,它们最终可能会有相同的值。
答案 14 :(得分:0)
我将在此之前加上“我不是一个网络人,所以我可能会跟随完全不连贯的句子。”
当我在伊利诺伊州立大学工作时,我们有两台戴尔台式机,在不同时间订购。我们把第一个放在网络上,但当我们试图将第二个放在网络上时,我们开始收到疯狂的错误。经过多次故障排除后,确定两台机器都生成相同的GUID(我不确定究竟是什么用,但它使它们在网络上都无法使用)。戴尔实际上将这两台机器更换为有缺陷的。
答案 15 :(得分:0)
如果用户使用不同的带有网卡的机器,则不可能,即使不是,它仍然是一个非常边缘的理论风险。
就个人而言,我会在其他地方寻找,因为它更可能是一个错误,而不是GUID冲突......
当然,您不要将GUID上的位切掉,以缩短它。
答案 16 :(得分:0)
如果您通过SQL Server中的NEWID()
函数生成它们,那么您很可能会遇到GUID冲突(尽管当然可能,正如其他答案所强调的那样)。他们没有指出的一件事是,如果你在野外的浏览器中使用JavaScript生成GUID,那么你很可能会遇到冲突。不仅在不同的浏览器中RNG有时会出现问题,但我也遇到了一些问题,谷歌蜘蛛似乎会缓存这类功能的结果,并最终反复将相同的GUID传递给我们的系统。
有关详细信息,请参阅此处的各种答案:
答案 17 :(得分:0)
您是数学家吗?那是的。
您是工程师吗?那不行。