我有一个包含数千行的表,此表有一列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
相同的模式,但从一次迭代到下一次迭代可能具有更多的唯一性。
我希望我在这个解释中足够清楚。
答案 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个字符将有很多组合。