【问题标题】:Pros and cons of using md5 hash of URI as the primary key in a database使用 URI 的 md5 哈希作为数据库中的主键的优缺点
【发布时间】:2010-09-18 06:45:49
【问题描述】:

我正在构建一个数据库,该数据库将存储有关一系列对象(例如科学论文、标本、DNA 序列等)的信息,这些对象都在网上存在并且可以通过 URL 或标识符等标识作为DOI。使用这些 GUID 作为对象的主键似乎是一个合理的想法,我遵循 deliciousConnotea 使用 GUID 的 md5 哈希。如果您将鼠标悬停在美味或 Connotea 书签中的编辑或删除按钮上,您将在浏览器状态栏中看到 md5 哈希。例如,http://stackoverflow/ 的书签是

http://delicious.com/url/e4a42d992025b928a586b8bdc36ad38d

其中 e4a42d992025b928a586b8bdc36ad38d 是 http://stackoverflow/ 的 md5 哈希。

有人对这种方法的优缺点有看法吗?

对我来说,这种方法的一个优点(与使用由数据库本身生成的自动递增主键相反)是我必须在对象之间做很多链接,并且通过使用 md5 哈希,我可以将这些链接存储在外部在一个文件中(例如,作为数据挖掘/抓取的结果),然后将它们批量导入数据库。同样,如果必须从头开始重建数据库,则指向对象的 URL 不会更改,因为它们使用 md5 哈希。

我欢迎任何关于这听起来是否合理的想法,或者是否有其他(更好的?)方法。

【问题讨论】:

  • 您最终是否使用 md5 作为主键?进展如何?
  • 任何非唯一值都可以用于索引,但不能用于 PK。

标签: database primary-key guid md5 uri


【解决方案1】:

md5 散列几乎是唯一的,但不是完全唯一的,所以不要将它用作主键。它因加密使用而折旧。密钥冲突的可能性较小,但如果你有数十亿行的相当大的数据库,仍然有一些冲突的机会。如果您坚持使用散列作为主键,请使用其他更好的散列。您不能对主键使用非唯一值。 如果您有很大的桌子,请不要使用它。如果你有小桌子,你可能会使用它,但不推荐。

【讨论】:

    【解决方案2】:

    完全没问题。

    MD5 的意外碰撞在所有实际情况下都是不可能的(要获得 50% 的碰撞机会,您必须每秒散列 6 十亿 个 URL,每秒 , 100 年)。

    这是一个非常不可能的机会,您因未检测到的硬件故障而导致数据混乱的可能性是实际碰撞导致的数万亿倍。

    尽管存在针对 MD5 的已知冲突攻击,但目前不可能针对散列 URL 进行故意恶意冲突。

    • 您需要故意与另一个 URL 的哈希冲突的冲突类型称为 pre-image 攻击。没有已知的针对 MD5 的前映像攻击。截至 2017 年,还没有任何研究接近于可行性,因此即使是坚定的资金充足的攻击者也无法计算出可以散列为数据库中任何现有 URL 的散列的 URL。

    • 唯一已知的针对 MD5 的冲突攻击对于攻击类似 URL 的密钥没有用处。它通过生成一对只相互碰撞的二进制blob来工作。这些 blob 相对较长,包含 NUL 和其他不可打印的字节,因此它们极不可能类似于 URL。

    【讨论】:

    • 没错。您仍然需要注意,故意的 MD5 哈希冲突是容易做到的。如果这将成为一个问题,您最好使用 SHA-1 或其他一些不像 MD5 那样损坏的新散列函数。
    【解决方案3】:

    MD5 被认为已弃用 - 至少出于加密目的,但我建议仅使用 md5 来向后兼容现有内容。当我们确实有其他未(至少)未损坏的哈希算法时,您应该有充分的理由使用 md5。

    我在该方法中看到的问题:

    • 重复对象,因为url标识符不同 (正如arend提到的)
    • 网址发生变化

    后者可能很重要 - 这可以像删除和添加一样简单地完成。也就是说,如果这些 id 在数据库之外永远不可见/不可存储。 (就像作为 URL 的组成部分一样。)

    我想这些对于 DOI 来说都不是问题。


    如何使用非自动编号整数 id 设置,但离线插入器代理在哪里创建数字? (可以使用专用的数字范围吗?) 如果两个用户独立添加相同的 url,可能会出现重复问题?

    【讨论】:

    • 他问的是索引,而不是加密。如果碰撞是故意的或随机的,情况就大不相同了。最后,这取决于他是否可以忍受随机碰撞的问题。
    【解决方案4】:

    多个字符串可以产生相同的 md5 哈希。主键必须是唯一的。所以使用散列作为主键是不好的。最好直接使用 GUID。

    是适合在 URL 中使用的 GUID。当然。这是我使用 Java 创建的 GUID(实际上是 UUID):1ccb9467-e326-4fed-b9a7-7edcba52be84

    网址可以是:

    http://example.com/view?id=1ccb9467-e326-4fed-b9a7-7edcba52be84
    

    它有点长,但完全可用,并且达到了您的描述。

    【讨论】:

    • 但是如果我想在 URL 中使用主键,我需要重新格式化它,而不是仅仅使用 md5 哈希。我希望让事情变得简单。
    • 为什么需要重新格式化? Internet Archive 逐字使用 URL,作为归档页面 URL 的子字符串。
    • rdmpage -- Md5 不是唯一的。因此,它不适合作为主键。
    • 但是如果发生碰撞的概率很低,那么这不是一个大问题。另外,与 UUID 不同,我可以保证我可以从相同的 URI 重新生成相同的 md5 哈希,例如,如果 GUID 是在不同的时间生成的,这很有用。 UUID 似乎解决了一个不同的问题。
    • Hugh -- 但是有些 URI 非常混乱,可能包含 url 编码的部分和未编码的部分,等等,让生活变得困难。哈希似乎更容易管理。
    【解决方案5】:

    在进一步浏览了 stackoverfow 之后,我发现了一个较早的问题 Advantages and disadvantages of GUID / UUID database keys,它涵盖了大部分内容。

    【讨论】:

      【解决方案6】:

      通常很多不同的 url 指向同一个页面。 http://example.com/ 例子.com http://www.example.com/ http://example.com/index.html http://example.com/https://example.com/ 等等

      这对您来说可能是也可能不是问题。

      【讨论】:

      • 我确实对同一个对象有多个标识符(文章通常在网络上出现不止一个)。这不是一个大问题,我不依赖生成哈希的人来确定 URI 是否存在于我的数据库中。
      【解决方案7】:

      也许这份文件是你想读的:

      http://www.hpl.hp.com/techreports/2002/HPL-2002-216.pdf

      【讨论】:

      • 有趣的阅读,但略有不同的问题。此外,在我的情况下,内容可能会被编辑,但我希望保持 URI 不变。 HP 技术报告中的方法要求我在每次编辑时更改 URI。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-22
      • 2011-04-11
      • 2017-09-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多