【问题标题】:Is there a way to make GUID 100% collision-safe? [duplicate]有没有办法让 GUID 100% 防碰撞? [复制]
【发布时间】:2021-04-05 14:28:40
【问题描述】:

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

我正在使用 ASP.NET Core v5、Entity Framework Core v5.0.1、SQL Server。

请注意,我想要不可猜测的 ID-s(identity(1,1) 目前不是我的解决方案)

【问题讨论】:

  • 在单个表中唯一?添加一个唯一的约束,如果发生碰撞,则循环,它不会 - 工作完成。世界独一无二?没有。
  • GUID 就足够了。别担心。
  • 保证唯一性和不可猜测性是两个完全不同的东西。独特意味着不等于其他任何东西。 Un-guess-able 当然不可能,但是让最难猜测的东西的方法是让它加密随机,根据定义,它永远不会是 100% 唯一的(但你可以很很容易使可能性低于行星爆炸的可能性,这实际上对你来说可能已经足够好了,即使你不这么认为)。
  • @DorinBaba 是的,我告诉你,你必须选择其中一个。使其 100% 保证始终唯一的方法是使用可以确定不会重复的可预测模式。使某些事情尽可能难以猜测的方法是使用加密强度随机数生成器,这在技术上永远不可能重复,只是一种任意低的可能性。除非您有一个实体负责通过与所有其他现有值进行比较来验证唯一性(即对充满密码随机数据的列的唯一约束。
  • @xanatos 你没有理解。如果我想猜测序列中某个项目的值,或者要创建的下一个值,我只需从 0 开始计数,生成 N 的值,自己对值进行散列,生成 N2,并且知道我知道那个值我不应该猜到,也不需要尝试所有选项。

标签: c# sql-server entity-framework primary-key guid


【解决方案1】:

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

【讨论】:

  • 好吧,我问这个问题的原因是为了避免这一步。我想我不是唯一一个遇到这个问题的人:) 我想我会采用这种方法。谢谢!
  • @DorinBaba 正如我在下面解释的那样,这并没有真正降低发生冲突的可能性(除非您的数据库非常大)。它当然不能保证唯一性,因为您的碰撞检查代码中可能仍然存在错误,或者数据库引擎或硬件中可能存在错误。由于所有这些概率都高于 GUID 碰撞的可能性,因此使用这种方法实际上并没有降低碰撞的总概率。
【解决方案2】:

对于所有意图和目的,与随机 GUID 发生冲突的概率为 0。即使您发明了一个真正 100% 无冲突的 ID,冲突的概率在实践中也不会更低,因为您的 ID 生成器中存在错误或故障的概率尽管您生成了 ID,但由宇宙射线引起的计算机硬件会产生冲突,这与 GUID 冲突的可能性一样重要。

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

p(n) = 1 - (1-1/m)(1-2/m)...(1-(n-1)/m)
     ≈ n^2 / (2m)

假设n = 1,000,000,000。那样的话

p(n) ≈ (10^9)^2 / (2 * 2^122)
     ≈ 9.4 x 10^-20

在 72 小时内出现 RAM 错误(即使使用 ECC)的probability 是天文数字!

所以答案是:GUID 与您在真实物理世界中的真实物理计算机上的碰撞安全性一样高。

【讨论】:

猜你喜欢
  • 2015-01-16
  • 2020-03-16
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多