在MySQL数据库中存储大文件的更好方法?

时间:2010-10-08 21:02:16

标签: php mysql file-upload storage large-files

我有一个PHP脚本,你可以上传非常大的文件(最多500MB),文件的内容存储在MySQL数据库中。目前我这样做:

mysql_query("INSERT INTO table VALUES('')");

$uploadedfile = fopen($_FILES['file']['tmp_name'], 'rb');
while (!feof($uploadedfile)) {
    $line = mysql_escape_string(fgets($uploadedfile, 4096));
    mysql_query("UPDATE table SET file = CONCAT(file, '$line') WHERE something = something");
}
fclose($uploadedfile);

这当然会进行大量的SQL查询。

我这样做而非

$file = file_get_contents($_FILES['file']['tmp_name']);
mysql_query("INSERT INTO table VALUES('$file')");

因为这会占用文件的大量内存,并且执行更多sql查询似乎比使用500 MB内存更好。
但是,必须有更好的方法。我应该继续以file_get_contents方式进行,还是比CONCAT更好的方式,或者我现在这样做的方式是所有邪恶中的较小者?

6 个答案:

答案 0 :(得分:3)

我总是将我的文件存储在服务器上,并将其位置存储在数据库中。

答案 1 :(得分:2)

你是对的,在某些情况下,文件系统无法完成这项工作。因为数据库具有诸如锁定,复制,完整性,行数限制等功能等...文件系统中不存在。

此外,备份/恢复/迁移系统变得更加复杂,无法在正在运行的服务器上安全地完成(存在不一致和数据丢失的风险)。或者至少在DB + FS配置中保证这一点非常困难。

从" /"迁移怎么样?基于分隔符的操作系统到" \"基于一个?您需要更新所有路径。

您的方法似乎是正确的,但4096字节切片太小了。例如,Mysql在处理256kb切片时没有任何问题。

另外,我不会连接,而是将每个切片存储为单个记录。数据库可能无法在单个记录中存储大量文件,这可能会遇到其他答案中提到的限制。

保持数据切片将允许流式传输内容,而无需将整个数据存储在内存中。这样,存储的文件大小几乎没有限制。

答案 2 :(得分:1)

这对于mySQl实际上不起作用(默认情况下),因为这会导致500 MB的大查询。

$file = file_get_contents($_FILES['file']['tmp_name']);
mysql_query("INSERT INTO table VALUES('$file')");

因为max_allowed_packet设置为16777216.您可能需要增加它或将其拆分为小于16 MB的块(减去查询字符串的查询~500-1000字节)。

您可以通过查询

找到mysql服务器的max_allowed_pa​​cket
SELECT @@global.max_allowed_packet

答案 3 :(得分:0)

我想成像,最有效的方法是在脚本中执行所有验证,直到插入点,然后弹出并执行上传的$ FILES临时文件的文件移动。 MySQL命令行插入查询。你想要一个比bash更好的人来验证它,但似乎它几乎会消除内存问题?

答案 4 :(得分:0)

我还没有看到实际需要在关系数据库中存储文件的应用程序。

有大量免费提供的,功能强大的数据库,专门用于存储/检索文件而设计和优化。 他们被称为文件系统

将文件存储在文件系统中,将元数据存储在RDBMS中。

你担心在插入时会耗尽500MB的内存,而且不清楚原因。你最终想要从数据库中取出这些文件,我认为你不会找到一种方法来读取文件数据。

答案 5 :(得分:0)

您可以使用:

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_load-file 它还提供了一个简单的查询示例。