生成非重复数字,警惕数据库

时间:2015-05-10 22:17:39

标签: php mysql

我希望根据MySQL数据库生成一个没有重复的随机数。如何更改以下函数,以便在生成的数字已存在时检查数据库,如果不存在,则将它们插入表中。此外,该表应如何布置?我不是最好设计行,以使它们尽可能小(和实用)。

功能:

function genNonRepNum($min, $max, $quantity) {
    $numbers = range($min, $max);
    shuffle($numbers);
    return array_slice($numbers, 0, $quantity);
}


使用该功能:

print_r(genNonRepNum(1000, 10000, 3));

返回:

Array ( [0] => 8586 [1] => 9666 [2] => 8169 )

哪个很棒,但我只希望它检查数据库是否存在,如果不存在则插入数据库。提前谢谢。

2 个答案:

答案 0 :(得分:0)

我认为这不是你应该采用的方式,只需使用php openssl-random-pseudo-bytes,它会为你提供一串随机字节(任何可以创建不可预测的安全ID的加密安全随机生成器/哈希函数)会做的工作) - 这将给出肯定不同的键(或理论上不太可能是相同的)或者如果你想要一个好的数字使用自动增量并获得你的驱动程序提供的lastinsert_id,例如:

mysqli_insert_id()
PDO::lastInsertId()
查询执行后

并在软件中使用

手动检查是否插入和重试既昂贵又不好,应该避免

请尽量将您到数据库的行程保持在最低限度!!!!!!!

答案 1 :(得分:0)

首先,通常你不会这样做 - 你可以设计一个足够大的数字,使碰撞概率可以忽略不计,然后使用强大的随机生成器生成那个大小的随机数。

否则,因为你必须存储数字(除非你实施某种深奥的加密方案 - 你可以存储一个计数器并使用AES加密它;当然这些数字不是真正的“随机”) ,但它们也不容易预测),你必须在开始时定义随机范围,你可以创建一个已经插入随机数的表:用连续数字填充一个表,然后用唯一的auto_increment插入到另一个表中按兰德()的密钥排序。

现在,当您需要一个随机数时,您将获取表的第i个元素并读取其value列,然后递增i以确保您不重复使用该数字。如果两个进程都需要一个随机数,你会想要使用锁定和事务。

这也有一个好处就是提前知道号码池何时会变干;此时您可以插入新号码。这将略微随机(在0-999999范围内,第一百万个数字将是随机数,第二百万个数字将在1000000-1999999范围内),但也许它足以满足您的需要。

或者您可以使用两个UNIQUE列创建随机表

CREATE TABLE randompool (
    id integer not null primary key auto_increment,
    value integer
);
CREATE UNIQUE INDEX randompool_uniq ON randompool(value);

并使用辅助进程来检查某个地方保存的全局变量NEXT_ID何时在COUNT(*) FROM randompool的10%以内 - 这意味着随机池的容量降低到10% - 如果是,则生成一些随机数和尝试插入

INSERT IGNORE INTO randompool (value) VALUES (?),(?),(?),...

当然,randompool越大,此操作效率越低。当randompool包含2亿个数字时,生成随机正号32位数字将有10%的概率命中重复并被拒绝,因此插入1000个新随机数的成本将比开始时的成本高;还要考虑索引重复查找会花费更多。不是更多,但更多。但是,如果该过程是独立的并且在系统没有过载的情况下运行,那么这可能不是问题。

随机数的选择仍然会使用NEXT_ID计数器直接从表中获取它们,因此读取数字将非常便宜。