为 MySql 生成完全不同的 UUID

Generating completely different UUID for MySql

我在 SO 上看到过其他类似的问题,但我在这里问的问题在那里没有得到回答。

我的 table 上有一个名为 GUID 的字段,它是主键。

我希望每次插入记录时都用随机 UUID 填充此字段。

所以,我创建了这个 table:

CREATE TABLE `myTable` (
  `id` int(6) NOT NULL,
  `first_name` varchar(64) NOT NULL,
  `last_name` varchar(64) NOT NULL,
  `GUID` char(40) NOT NULL,
   PRIMARY KEY(`GUID`) 

) ENGINE=MyISAM DEFAULT CHARSET=latin1;

DELIMITER //
CREATE TRIGGER `t_GUID` BEFORE INSERT ON `myTable`
 FOR EACH ROW begin
 SET new.GUID := (SELECT uuid());
END //
DELIMITER ;

我已向此 table 插入了 4 条新记录,这些是添加到条目中的 UUID:

除了 3 个数字外,这些基本上是相同的 UUID。

如何在插入新记录时生成 table 唯一的完全不同的 UUID?

为了回答您的问题,是的,guid 或 uuid 并非设计为难以预测。它只是被设计成独一无二的,这是一项非常困难的任务。

拥有像这样的大主键确实会耗尽 space,从而降低性能。

除非万不得已,否则我不会推荐它。通常人们在预先计划将数据分片到多个表中时会使用 guid 作为键。

反对这样做的另一个论点是混淆不是安全的。如果从安全角度来看存在问题,有人看到了他们不应该看到的东西,因为他们访问了 url 和 id=3,那么如果 url 是 id=ae353c26-9022-11ea-b775-1866daed31d4。该应用程序不应允许某人访问 id=3,如果他们不应该能够访问它的话。

话虽如此,用于此类方案的一种解决方法是对输入进行哈希处理。

您可以使用 uuid 与行中的一些数据连接,也许还有时间戳,以及一些随机的东西和 运行 例如通过 sha1() 。它将产生一个 40 个字符的大十六进制字符串。

可能会发生碰撞,因此您可能需要检查并从中恢复。

CREATE TABLE `myTable` (
  `id` int(6) NOT NULL,
  `first_name` varchar(64) NOT NULL,
  `last_name` varchar(64) NOT NULL,
  `GUID` char(40) NOT NULL,
   PRIMARY KEY(`GUID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

DELIMITER //

CREATE TRIGGER `t_GUID` BEFORE INSERT ON `myTable`
 FOR EACH ROW begin
 SET new.GUID := (SELECT SHA1(CONCAT(new.first_name, RAND(), UUID(), new.last_name, NOW())));
END //
DELIMITER ;

uuid() 函数生成 UUIDv1,其定义方式相当可预测。如果您非常快速地生成一堆新值,它们只会相差几位——但它们仍然保证是唯一的。

如果你想要不可预测的值,那么你需要切换到生成UUIDv4的函数。这仅在统计上是独一无二的,但除非您在数十亿年内每秒生成数十亿个值,否则它在实践中已经足够好了。

旁白:您可能需要考虑将 UUID 存储为 BINARY(16) 以节省 space 并提高搜索效率。如果您需要在数据库中进行故障排除,可以使用生成的列来获取文本版本。