我需要为上传的文件生成唯一的文件名。我将名称存储在数据库中,并在生成文件名时检查以确保它是唯一的。我知道这里有很多关于这个问题的问题,但是我试图理解的是为什么我的脚本不起作用。
她的代码是获取文件名并检查它是否唯一:
do {
$newName = generateRandomString(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
$stmt = $this->db->prepare('SELECT id FROM images WHERE file_name = :newName');
makeQuery($stmt, array(':newName' => $newName));
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
} while(!empty($row));
generateRandomString()
的位置:
function generateRandomString($length, $characters) {
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomString;
}
现在,当我在我的数据库中运行大约30,000个文件名时,需要几秒钟到几个分钟来返回文件名。
如果我在文件名(0-9a-zA-Z)中使用的字符数量和长度都是10,那么应该有大量潜在的文件名(如果我计算它的话,大约需要1070亿)对)。看起来根本不应该有任何碰撞,最不重要的是我得到的数字(我分析的一个XDebug配置文件快照说generateRandomString()
跑过 100,000 回来之前!)。
为什么这不起作用,我该怎么做才能解决它?
编辑:哎呀,我误解了xdebug数据。它没有进行100,000次函数调用,花了123,502毫秒(所以时间,而不是函数调用)。答案 0 :(得分:2)
此代码存在许多问题:
SELECT
,然后INSERT
容易出现竞争条件(在两个语句之间,另一个进程插入了相同的ID)。干净的方法是乐观地插入一行,并重复重复键错误,更好地使用确定性的独特功能。rand()
函数,它根据PHP版本和操作系统产生完全不同的随机性。使用mt_rand();
我建议您在数据库中创建标识符:请参阅我的answer to another SO question
答案 1 :(得分:0)
我想我找到了解决方案:
http://kvz.io/blog/2009/06/10/create-short-ids-with-php-like-youtube-or-tinyurl/
此代码生成的所有ID都是唯一的