【问题标题】:How to Prevent MySQL UUID V1 Collision如何防止 MySQL UUID V1 冲突
【发布时间】:2016-01-04 03:30:38
【问题描述】:

我们的 API 旨在为所有记录在 MySQL 中生成 UUID。

但是,所有表中生成的 99% 的记录共享相同的 UUID 的最后 3 个块。我假设这是因为 MySQL 使用 v1 的 UUID,它基于 Mac 地址,在同一台服务器上不会改变。熵似乎不足以对唯一性有高度的信心。

例如XXXXXXX-XXXX-46fc-bb08-f9b12276ed01

这是根据维基百科验证的:

“鉴于现代处理器的速度,在同一台机器上连续调用版本 1 UUID 的生成器的幼稚实现可能会产生相同的 UUID,从而违反唯一性属性。(非幼稚实现可以通过以下方式避免此问题,例如,记住最近生成的 UUID,“装袋”未使用的 UUID,并使用装袋的 UUID,以防即将生成重复。)”

听起来,如果在一定时间内进行了足够多的 API 调用,那么冲突将是肯定的(只是达到交易量的问题,例如每秒 1000 笔交易?即接近每毫秒 1 笔交易)。

假设:UUID() 是 MySQL 二进制文件的函数,无法更改。

我需要在多大程度上评估更改以防止冲突,以及如何使 wikipedia 推荐的 MySQL 更改为“口袋”UUID?

【问题讨论】:

    标签: mysql uuid


    【解决方案1】:

    在您的 UUID 列上设置唯一约束。这将使数据库在插入(或更新)记录之前检查重复项,因此您可以确保表中没有冲突。碰撞记录将无法插入。

    如果您发现由于违反该约束而实际上出现了错误——即,如果冲突实际上发生在 UUID 生成器中并且数据库将它们排除在表之外——那么你可以研究更复杂的方法来生成新的 UUID 并重试。但很有可能,您不会有任何问题。

    UUID 中的时间戳字段以 100 纳秒为间隔,因此您必须在十分之一微秒内生成两个 UUID 才能发生冲突。这对应于每秒一千万次交易的速度。一千应该没问题。

    【讨论】:

    • 除了时间戳还有时钟序列,似乎是随机播种的;每次生成 UUID 时都会递增。这实际上是 10 位,这意味着您必须每 100 纳秒间隔生成数千个 UUID,然后才会有发生碰撞的危险。一个好的 UUID 实现需要做的就是在线程之间共享这个序列,并将其锁定几皮秒以确保不会发生冲突。然而,当前的硬件不应该足够快以至于需要它。请记住,这也是每台机器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    • 2019-05-07
    相关资源
    最近更新 更多