【问题标题】:MySQL BLOB image data gradually losing?MySQL BLOB 图像数据逐渐丢失?
【发布时间】:2012-06-16 02:06:29
【问题描述】:

在 mysql MyISAM 表中,我有一个列类型 mediumblob 并将捕获的图像存储为 blob 数据。我得到了一些有趣且有问题的图像。部分图片为gradually losing 数据。

Field          type  
--------------------------
image         mediumblob

my.ini最大允许数据包大小集max_allowed_packet = 8M

这就是问题

C# 应用程序从服务器获取数据时,这种图像每次都会丢失随机大小的数据。我在100000+ 图像数据中得到了10-12 这样的坏图像。

这种行为的原因可能是什么?任何人都知道如何解决/避免这个问题。

更新 1:
从 PictureBox 中读取字节

MemoryStream ms = new MemoryStream();
byte[] ret = null;

try
{
     picturebox.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
     byte[] Data = new byte[ms.Length];
     ms.Read(Data, 0, (int)ms.Length);
     ret = byteData;
     ms.Close();
 }         
 

将字节数组作为中等 blob 数据保存到数据库中。从数据库中检索数据时,我正在投射阅读器数据:

byte[] Data = (byte[])reader["Image"];

【问题讨论】:

  • 如果您将图像存储在数据库中,您会遇到麻烦。为什么不将它们存储为常规文件?
  • @niksonkantiPaul 我只是好奇你为什么将图像保存到数据库中,而不仅仅是路径和图像到文件夹中?

标签: c# mysql image image-processing blob


【解决方案1】:

首先,正如 Sarke 所提到的,将文件内容存储在 DB 中并不是最好的主意(文件元数据是完全不同的故事。

为什么?

  1. 性能:在大多数情况下,操作系统文件缓存的性能将优于 DBMS 中内置的任何内容。
  2. 灾难恢复:发生故障时丢失所有/大多数文件的几率远高于使用文件系统的情况,而且恢复要困难得多
  3. 扩展:如果您超出单个服务器的容量,则添加应用程序级分片是微不足道的,并且不会降低性能。多服务器数据库设置更“痛苦”
  4. 提供多种解决方案/易于迁移:有大量用于存储大型文件集合的硬件和软件解决方案,并且它们之间的迁移比 DBMS 之间的迁移简单得多

我存储了近 200 万张图像,这些图像存储在一个简单的文件夹结构中:/xx/yy/filename,其中文件名 = 文件的 md5(+ 发生哈希冲突时的可选数字),xx = md5 的前 2 个字符,yy = md5 的第 3 和第 4 个字符。它工作得很好,我不应该在很长一段时间内遇到任何与 FS 相关的减速(至少 2 个数量级)。

回到您的问题,有 3 个选项

  1. 文件永远不会正确保存到数据库中。上传照片的应用程序可能有问题或图像太大。您的 max_allowed_packet 将图像大小限制为 ~8 MB,mediub_blob 最多可以存储 16 MB。要排除这一点,请将max_allowed_packet 增加到 32 MB 并进行测试。您需要确保任何时候都没有图像超过此大小,并确保应用程序在上传照片时能正常工作。如果您可以找到上传并显示正常的图像(来自 DB!),但后来却没有,那么这不是原因。
  2. 文件在更新过程中损坏 - 如果有任何东西以任何方式更新照片,那么即使原始文件没问题,更新后的文件也可能不会 - 例如,它可能超过第 1 点的大小限制。
  3. (最不可能的)如果文件在没有损坏的情况下被存储和更新,那么它在存储时会被损坏 -> 没有报告 MySQL 错误(这不会被忽视)我会看服务器硬件。

【讨论】:

  • 只是为了确保:您已确认图像没问题(至少从数据库中提取了一次未损坏的图像),后来才发现它们现在已损坏?
  • 存储为文件?这是个坏主意,而且性能也很差,看看 S3、azure blob store,它们是专门为更大的文件存储而设计的。
  • @AkashKava S3 也不使用关系数据库进行文件存储 - 它们使用键值存储 (Amazon Dynamo)。只有当您的网站/服务增长到可以从地理复制等中获利时,这种存储解决方案才优于文件存储 - 功能超越了简单的存储到内容交付、备份、自动优化等。
【解决方案2】:

罪魁祸首是 MyISAM 存储类型。

我们使用 InnoDB 存储存储了 100 万张图像并进行了压力测试,我们得到了正确的结果。要么文件被正确检索,要么根本没有被检索(小于 0.01%),因为 InnoDB 是酸兼容的。

当我们转移到 MyISAM 时,丢失数据的故障率增加到 20%,与您的情况相同。原因是,MyISAM 使用表锁,所以在写入过程中,整个表都被锁定,并且在超时的情况下,它确实会覆盖导致数据丢失的内容。

我们现在已经将所有内容都转移到了 MS SQL,因为 InnoDB 性能良好但它仍然从不重用已删除的文件空间,因此 InnoDB 不断地增长。 MS SQL express 有 10gb 的限制,所以我们创建了 4-8gb 的页面并在那里存储 blob。我们有自己的自定义复制,可以通过相同的配置在网络上的三台服务器上复制文件。

在磁盘上存储文件是不好的,原因有很多,每个人都在说文件系统是为高性能而设计的,可以存储数百万个文件,这是不正确的,当你有超过 10 万个文件时,驱动器无法更快地执行。它们在处理一个大文件然后处理 1000 个小文件时表现良好。目前我们正在存储 1000 万个文件并将其存储在 db 中更有意义,因为 db 对查询进行了优化并进行了良好的缓存。你可以在http://akashkava.com/blog/127/huge-file-storage-in-database-instead-of-file-system/阅读更多内容

这就是发明 MongoDb、Hadoop、Azure Blob Store、Haystack 和 Amazon S3 的确切原因。

【讨论】:

    【解决方案3】:

    我认为您首先需要弄清楚是您的应用程序还是某些外部进程(备份/恢复?)更改了这些数据。 实际上,如果文件应该保持不变,我认为您的应用程序需要更新这张图片(即使用相同的数据更新字段)的理由很少。

    一旦您发现应用程序的哪些部分更新了此字段,您可能需要发布一些代码以查看是否没有发生转换、转义或其他任何事情。

    如果我认为这种更新永远不会发生,那么在表上设置BEFORE UPDATE 触发器将使您能够准确地知道问题何时发生,并且可能有助于识别可能的模式。比较 OLDNEW 的值并在日志表中记录尽可能多的相关可用数据 - 请注意,比较大型 BLOB 可能会成为性能杀手,请密切关注您的性能。

    【讨论】:

      【解决方案4】:

      我的公司选择将图像存储在数据库之外。我们注意到,与您使用的 Blob 一样,Blob 很容易出现损坏和性能问题。我们在 MSSQL、Sybase 和 Faircom 中看到了同样的问题。

      每当应用程序需要访问图像时,它都需要访问可以找到该图像的网络(或基于 Web)存储。然后数据只存储图像的路径。

      由于图像是文件系统中某处的平面文件,如果需要更新记录(即添加注释以描述图像),它自身的图像不会重新编译到 blob 中,并且存在它没有被损坏的机会。

      【讨论】:

      • 那么为什么它会在同一张图片中反复发生:(,
      • 您的程序是否曾经重写记录(包括 Blob 字段)?
      【解决方案5】:

      您使用什么 API 从数据库中获取数据? 给我们一些获取数据的代码。

      通常使用某种“流”从数据库中读取 BLOB,因此如果您使用它,可能需要切换到比 ADO.NET 更强大的东西。

      此页面可能有用:http://dev.mysql.com/doc/refman/5.5/en/connector-net-programming-blob.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-01
        • 2014-11-22
        • 1970-01-01
        • 1970-01-01
        • 2015-01-31
        • 2012-03-05
        • 2010-10-23
        • 2012-07-16
        相关资源
        最近更新 更多