MySQL BLOB图像数据逐渐丢失?

时间:2012-06-13 06:36:08

标签: c# mysql image image-processing blob

在mysql MyISAM类型表中有一列Image类型mediumblob并存储捕获的图像。我得到了一些有趣且有问题的图像。一些图像是gradually losing数据。

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

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

image1 image2 image3

这是问题

C#应用程序每次从服务器获取数据时,这些图像逐渐丢失数据并随机大小。我在10-12图片数据中收到了100000+个错误的图片。

这种行为可能是什么原因?任何人都有任何想法/解决方案如何解决/避免这个问题。

更新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();
 }         

将bytes数组作为中等blob数据保存到数据库中。从数据库中检索数据时,我正在转换读者数据

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

5 个答案:

答案 0 :(得分:5)

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

为什么呢?

  1. 性能:在大多数情况下,操作系统文件缓存将优于DBMS内置的任何内容。
  2. 灾难恢复:失败时丢失所有/大多数文件的几率远高于文件系统,恢复要困难得多
  3. 缩放:如果您增加单个服务器的容量,添加应用程序级别分片是微不足道的,并且没有性能损失。多服务器数据库设置更“痛苦”
  4. 提供多种解决方案/易于迁移:大型文件集存储有大量硬件和软件解决方案,在它们之间迁移比在DBMS之间迁移要简单得多
  5. 我存储了近200万张图像,这些图像存储在一个简单的文件夹结构中:/xx/yy/filename,其中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错误(这不会被忽视)我会看服务器硬件。

答案 1 :(得分:4)

Culprit是MyISAM存储类型。

我们使用InnoDB存储来存储一百万张图像并进行压力测试,我们得到了正确的结果。由于InnoDB符合酸性,因此无法正确检索文件或完全没有检索到文件(小于0.01%)。

当我们转移到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的确切原因。

答案 2 :(得分:2)

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

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

如果我假设这样的更新永远不会发生,那么在表格上设置BEFORE UPDATE触发器可以让您确切知道问题何时发生,并可能有助于识别可能的模式。比较OLDNEW值并在日志表中记录尽可能多的相关可用数据 - 注意,比较大型BLOB可能是性能杀手,密切观察您的表现。

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:0)

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

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

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