MySQL UUID替代方案 - 更随机

时间:2017-06-19 22:24:18

标签: mysql

我有一个包含数千行的表,此表有一列guid。这通常在代码中生成,并且工作正常。

但是,这次执行了批量导入,但不包含UUID值。我现在需要更新此表,以便它正确地具有UUID值。

我遇到的问题是当我在循环中执行以下操作时:

(select uuid())

它不是随机。这意味着在内部,机器(名称?)和时间戳用于生成uuid,这导致数十万行接收超级相似的UUID。

不幸的是,我不能在软件堆栈中生成这个,所以我想知道是否有人有任何提示或良好的解决方案。

修改对于那些近距离投票:

(select uuid())命令中对数千行使用update时,它依赖于计算机(节点)和时间戳。因为成千上万的行在彼此的微秒内更新,这会在所有行中生成一个不幸的类似字符串,例如:

1a5e308e-5530-11e7-a853-932d273ec009
1a5e3160-5530-11e7-a853-932d273ec009
1a5e32a0-5530-11e7-a853-932d273ec009

将生成并应用于更新查询中前3行的前3个uuid。这是有问题的,因为这些UUID用于前端可见的连接字符串的更大部分。因此,最终结果是这些变得可猜测,因此代表了矢量攻击的可能角度。

我提出这个问题的目的是,是否有另一种方法来生成一个16字符,128字节的字符串,其遵循与UUID相同的模式,但从一次迭代到下一次迭代可能具有更多的唯一性。

我希望我在这个解释中足够清楚。

2 个答案:

答案 0 :(得分:2)

此函数在MySQL中生成完全随机的UUID(已通过MySQL 5.6测试)

select LOWER(CONCAT(
    LPAD(HEX(ROUND(rand()*POW(2,32))), 8, '0'), '-',
    LPAD(HEX(ROUND(rand()*POW(2,16))), 4, '0'), '-',
    LPAD(HEX(ROUND(rand()*POW(2,16))), 4, '0'), '-',
    LPAD(HEX(ROUND(rand()*POW(2,16))), 4, '0'), '-',
    LPAD(HEX(ROUND(rand()*POW(2,48))), 12, '0')
))

请注意,它不是UUIDv4,因为它没有表示版本4或变体的位(请参见UUIDv4 on Wikipedia)-相反,它是完全随机的(或更准确地说,与MySQL的RAND()一样随机)函数可以生成)

答案 1 :(得分:1)

您提到在相邻记录中使用类似的UUID时,这是一个安全问题。以下是如何使它更容易变得更好:

SELECT MD5(UUID());

SELECT sha1(UUID());

在这种情况下,没人能猜出下一个ID。如果你只需要16个字符,也许你可以SELECT LEFT(MD5(UUID()),16)。可能会有碰撞的机会,但机会仍然很遥远,因为MD5会提供  340,000,000,000,000,000,000,000,000,000,000,000,000,000,000个可能的独特产出,甚至前16个字符将有很多组合。