我找到了一种生成伪随机MySQLID的简单方法,这种方法有什么问题?
向用户公开自动递增的 ID 存在商业智能风险。我通常看到人们用来解决这个问题的方法是:
- 使用 GUID/MD5(比 4 字节 INT 大且慢)
- 生成整数,检查冲突,重复(慢,必须锁定表)
- 在应用程序中暴露“公共”ID(容易泄露实际 ID,可能会很慢)
相反,我创建了一个表:
CREATE TABLE `foo` (
`id` int unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
然后,每次插入一行时,我都会像这样手动插入 ID:
insert into `foo` (id) values (
last_insert_id((0xe8e5 * last_insert_id()) % power(2, 32))
);
该公式是一个线性同余生成器。我的理解是它会生成一个介于 1 和 2^32 之间的伪随机整数,除非所有 2^32-1 整数都用尽,否则不会发生冲突。参数0xe8e5来自https://arxiv.org/pdf/2001.05304.pdf
令人惊讶的是,这甚至适用于批量插入。另外,我尝试插入 100,000 行,但没有发生冲突。
我以前从未见过其他人这样做过,这有潜在的问题吗?
回答
您的特定方法存在一般技术问题,特定于last_insert_id()会话。这意味着另一个会话不会被告知该值的更改,并且很可能会重用一个 id。您还必须last_insert_id()在会话开始时进行初始化。此外,每次使用自动增量列(对于不同的表)都会重置该值。
您还应该注意,虽然它会模糊您的值,但这不一定是安全的,请参阅例如,如果给定序列,如何确定伪随机数生成器的初始值?.