【问题标题】:MySQL Binary Storage using BLOB VS OS File System: large files, large quantities, large problemsMySQL Binary Storage using BLOB VS OS File System:大文件、大数量、大问题
【发布时间】:2011-06-06 22:37:08
【问题描述】:

我正在运行的版本(基本上 最新的):
PHP:5.3.1
MySQL:5.1.41
阿帕奇:2.2.14
操作系统:CentOS(最新)

情况如下。

我有数千份非常重要的文件,从客户合同到语音签名(合同客户授权记录),文件类型包括但不限于 jpg、gif、png、tiff、doc、docx、xls、 wav、mp3、pdf等

所有这些文档目前都存储在多个服务器上,包括 Windows 32 位、CentOS 和 Mac 等。有些文件还存储在员工的台式电脑和笔记本电脑上,有些仍然是存储在数百个盒子和文件柜中的硬拷贝。

现在,由于客户或律师可以随时要求提供合同证据,我的公司必须能够有效地搜索和找到正确的文件,因此所有这些文件都必须数字化(如果还没有) 并关联到某种搜索和访问顺序。

作为程序员,我创建了一个全公司都使用的完整的客户关系管理工具。这包括客户资料管理、订单和工作跟踪工具、工作/销售创建和管理模块等,以及目前在客户资料级别(驾驶执照、信用授权等)或工作/销售级别(合同、语音签名等)可以上传到服务器并位于父/子层次结构中,就像 Windows 资源管理器或任何其他典型的文件管理模型一样。

结构如下所示:

drivers_license
|- DL_123.jpg
语音签名
|- VS_123.wav
|- VS_4567.wav
合同

所以文件是使用 PHP 和 Apache 上传的,并存储在操作系统的文件系统中。在上传时,有关文件的某些信息存储在 MySQL 数据库中。存储的一些信息是:

表格:文件上传
文件ID
CustomerID(文件所属的客户id,他们都有这个。)
JobID/SaleID(相关工作/销售的 ID,如果有的话。)
文件大小
文件类型
上传日期时间
上传者
FilePath(存储文件的目录路径。)
FileName(上传文件的当前文件名,CustomerID 和 JobID/SaleID 的组合,如果适用。)
文件说明
OriginalFileName(上传时源文件的原始名称,包括扩展名。)

如您所见,文件通过文件名链接到数据库。当我想将客户的文件提供给用户下载时,我所要做的就是“SELECT * FROM FileUploads WHERE CustomerID = 123 OR JobID = 2345;”这将输出我需要的所有文件详细信息,并使用 FilePath 和 FileName 我可以提供下载链接。

http...服务器/文件路径/文件名

这种方法有很多问题:

  1. 在这种“数据库无意识”环境中存储文件意味着无法保持数据完整性。如果一条记录被删除,该文件也可能不会被删除,反之亦然。
  2. 文件散落在各处,不同的服务器、计算机等。
  3. 文件名是唯一将二进制文件与数据库、客户资料和客户记录相匹配的东西。

等等等等。原因有很多,这里有一些描述:http://www.dreamwerx.net/site/article01。这里也有一篇有趣的文章:sietch.net/ViewNewsItem.aspx?NewsItemID=124。

所以,经过大量研究,我几乎决定将所有这些文件作为 BLOB 或 LONGBLOB 存储在数据库中,但在我这样做之前仍有许多考虑因素。

我知道将它们存储在数据库中是一个可行的选择,但是有许多存储它们的方法。我也知道存储它们是一回事。以可管理的方式关联和访问它们完全是另一回事。

此链接提供的文章:dreamwerx.net/site/article01 描述了一种将上传的二进制文件拆分为 64kb 块并使用 FileID 存储每个块,然后使用标头将实际二进制文件流式传输到客户端的方法。这是一个非常酷的想法,因为它减轻了服务器内存的压力;它不是将整个 100mb 文件加载到 RAM 中然后将其发送到客户端,而是一次执行 64kb。我已经尝试过这个(并更新了他的脚本),并且在非常小的测试框架内这是完全成功的。

因此,如果您同意此方法是一种可行、稳定且稳健的长期选择,可用于存储中等大小的文件(1kb 到几百兆)以及大量此类文件,请告诉我还有哪些其他注意事项或你有什么想法。

另外,我正在考虑获取一个当前的“文件管理”PHP 脚本,该脚本提供了一个界面,用于管理存储在文件系统中的文件并将其转换为管理存储在数据库中的文件。如果已经有任何软件可以做到这一点,请告诉我。

我想我可以问很多问题,所有信息都在那里^^所以请讨论这方面的各个方面,我们可以来回传递想法并互相教导。

干杯,

Quantico773

【问题讨论】:

  • 好的,您能提供任何理由说明为什么这是一个坏主意吗?我已经阅读了许多有关 MySQL 将二进制文件存储为 BLOB 或 LONGBLOB 的文章,它们的优点多于缺点。
  • 除了上面提到的那些文章,这里还有另一个提到存储在数据库中的一些好处:blogs.sitepoint.com/2006/10/15/…
  • 我最初的问题或讨论的全部目的是寻求更多关于这个正在发生的问题的文档,所以我很感激,但是,我会感谢争论双方的想法。谁有其他资源?
  • @ajreal - 你删除了所有的 cmets?做什么的?如果您删除它们,任何人都可以关注上面的有价值的对话吗??

标签: php mysql streaming http-headers blob


【解决方案1】:

我在一个大型软件系统上工作,该系统已经完成了存储附件和其他内容的两种机制。系统的第一次迭代将所有数据存储在数据库中的 BLOB 中。我当时诅咒它。作为一名程序员,我可以编写辅助脚本来立即对数据进行操作并随时更改。

前进了大约 10 年,我仍然管理相同的软件,但架构发生了变化,并且它是使用文件系统指针编写的。我现在诅咒它,希望它回到数据库中。我有几年的额外好处,并且在越来越多的更大情况下以更大的能力工作了这个应用程序,我觉得我现在的意见受到了更好的教育。应用程序的升级或系统迁移需要大量的脚本编写和数百万个文件的复制。有一次我们更改了操作系统,所有文件指针都有错误的目录分隔符,或者服务器名称更改了文件所在的位置,我们不得不在周末与 DBA 一起编写和安排简单的 SQL 更新语句来修复。另一个是文件系统和数据库记录不同步,为什么不确定但经过数千天的操作,有时非事务系统(文件系统和数据库不共享事务上下文)会变得不同步。有时文件会莫名其妙地丢失。

当所有这些都在数据库中时,迁移或环境升级就是转储和导入数据库的问题。可以正确审核行更改,同步的所有内容和日志可以在必要时重播到时间点。数据库肯定变大了,但现在是 2011 年,这对数据库来说根本不是挑战。

值得我们在流式传输一些数据时遇到一些类似的大型数据缓冲区问题,但是 A)我们可以使用 JDBC 中的 Input|OutputStreams 和 B)在使用其他工具时将数据泵入字节缓冲区,我们写道一个存储过程,它将 BLOB 分块到一个临时表中,并从临时表中迭代地提供这些块。效果很好。

我不在乎将这些东西放入数据库的技术原因是什么,但是在一个合并的位置管理起来要容易得多,我可以加倍并在管理不同文件的短时间内将顾问和客户浪费的时间增加三倍的硬件或网格数据库。


更新:对评论者放轻松,他们只是对此事发表意见。

【讨论】:

  • Xepoch,这是一些很好的信息,正是我想要的。你 10 年的经验给你上了宝贵的一课,我很高兴我在这里提出了这个问题。非常感谢您的宝贵时间。
  • 谢谢你,@Xepoch。这真的很有帮助。
猜你喜欢
  • 2022-01-11
  • 2016-12-07
  • 2014-11-07
  • 1970-01-01
  • 2011-01-07
  • 2011-06-01
  • 2021-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多