我找到了一种生成伪随机 MySQL ID 的简单方法,这种方法有什么问题?

Leo*_*ang 1 mysql random

向用户公开自动递增的 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;
Run Code Online (Sandbox Code Playgroud)

然后,每次插入一行时,我都会像这样手动插入 ID:

insert into `foo` (id) values (
    last_insert_id((0xe8e5 * last_insert_id()) % power(2, 32))
);
Run Code Online (Sandbox Code Playgroud)

该公式是一个线性同余生成器。我的理解是它会生成一个介于 1 和 2^32 之间的伪随机整数,除非所有 2^32-1 整数都用尽,否则不会发生冲突。参数0xe8e5来自https://arxiv.org/pdf/2001.05304.pdf

令人惊讶的是,这甚至适用于批量插入。另外,我尝试插入 100,000 行,但没有发生冲突。

我以前从未见过其他人这样做过,这有潜在的问题吗?

Sol*_*are 5

您的特定方法存在一般技术问题,特定于last_insert_id()会话。这意味着另一个会话不会被告知该值的更改,并且很可能会重用一个 id。您还必须last_insert_id()在会话开始时进行初始化。此外,每次使用自动增量列(对于不同的表)都会重置该值。

您还应该注意,虽然它会模糊您的值,但这不一定是安全的,请参阅例如,如果给定序列如何确定伪随机数生成器的初始值?.