C# 有没有办法使GUID 100%冲突安全?

C# 有没有办法使GUID 100%冲突安全?,c#,sql-server,entity-framework,primary-key,guid,C#,Sql Server,Entity Framework,Primary Key,Guid,我正在寻找一种方法来生成唯一的字符串作为数据库的主键。我知道GUID的冲突概率非常低,但我想知道是否可以使用它来获得100%唯一的密钥(99.99唯一性是不够的;) 我使用的是ASP.NET Core v5、实体框架Core v5.0.1和SQL Server 请注意,我需要不可猜测的ID-s(identity(1,1)目前对我来说不是一个解决方案)在没有顺序标识列的情况下保证唯一性的唯一方法是首先在表中查找ID,如果已经存在,则生成新ID。当然,这不是一个自由的操作,因此您需要权衡该检查的性能

我正在寻找一种方法来生成唯一的字符串作为数据库的主键。我知道GUID的冲突概率非常低,但我想知道是否可以使用它来获得100%唯一的密钥(99.99唯一性是不够的;)

我使用的是ASP.NET Core v5、实体框架Core v5.0.1和SQL Server


请注意,我需要不可猜测的ID-s(
identity(1,1)
目前对我来说不是一个解决方案)

在没有顺序标识列的情况下保证唯一性的唯一方法是首先在表中查找ID,如果已经存在,则生成新ID。当然,这不是一个自由的操作,因此您需要权衡该检查的性能影响与碰撞的概率(无穷小)。您最好尝试插入,如果发生冲突,则捕获错误并重试。

无论出于何种目的,与随机GUID发生冲突的概率都为0。即使您发明了一个真正的100%无碰撞ID,实际发生碰撞的概率也不会更低,因为,尽管生成了ID,但由于宇宙射线而导致的ID生成器中存在错误或计算机硬件出现故障并产生冲突的概率与GUID冲突的概率一样重要

要估计GUID冲突的大小,请将
n
作为数据库中的行数。随机GUID具有
m=122
随机位,因此数据库中至少发生一次冲突的概率为

p(n) = 1 - (1-1/m)(1-2/m)...(1-(n-1)/m)
     ≈ n^2 / (2m)
假设
n=100000000
。那么

p(n) ≈ (10^9)^2 / (2 * 2^122)
     ≈ 9.4 x 10^-20
在72小时内出现RAM错误(即使使用ECC)的可能性要高得多


因此,答案是:GUID是在真实物理世界中的真实物理计算机上可能得到的碰撞安全的GUID。

在单个表中是唯一的吗?添加一个唯一的约束,并在发生碰撞时循环,但不会发生碰撞-任务完成。世界上独一无二的?不,够了。别担心,保证独一无二和不可猜测是两件完全不同的事情。唯一的意思是不等于其他任何东西。不可猜测当然是不可能的,但让最难猜测的东西成为密码随机的,根据定义,这永远不会是100%唯一的(但你可以很容易地使可能性低于行星爆炸的可能性,这对你来说可能已经足够好了,即使你不这么认为)@DorinBaba是的,我告诉你你必须选择其中一个。让它100%保证永远唯一的方法是使用一个可预测的模式,你可以确保它不会重复。让事情尽可能难以猜测的方法是使用加密强度随机数生成器,这在技术上从来都是不可能的重复一下,这只是一个任意低的可能性。这是除非您有一个实体负责通过与所有其他现有值进行比较来验证唯一性(即,对一列充满加密随机数据的唯一约束。@xanatos,您不理解。如果我想猜测序列中某个项的值,或下一个要创建的值,我只需从0开始计数,生成N的值,自己对值进行散列,生成N2,并且知道我知道我不应该知道的值能够猜测,我不需要尝试所有选项。不。@xanatos我上面提供的公式是生日问题的近似值。@xanatos请看这里:当你在sqrt(总情况)附近时,生日悖论约为50%,sqrt(2^128)=2^64,低于宇宙中的原子(10^78到10^82个原子)当然,这也取决于生成器的质量。我的guid生成器有100%的冲突几率:)。我问这个问题的原因是为了避免这一步。我想我不是唯一一个有此问题的人:)我想我会采用这种方法。谢谢你!@DorinBaba,正如我在下面解释的那样,这并不会降低发生碰撞的概率(除非你的数据库非常大)。它当然不能保证唯一性,因为您的冲突检查代码中可能仍然存在错误,或者数据库引擎或硬件中可能存在错误。由于所有这些概率都高于GUID冲突的概率,因此使用这种方法,冲突的总概率实际上不会降低。