在mysql MyISAM
类型表中有一列Image
类型mediumblob
并存储捕获的图像。我得到了一些有趣且有问题的图像。一些图像是gradually losing
数据。
Field type
--------------------------
image mediumblob
my.ini
最大允许数据包大小设置max_allowed_packet = 8M
这是问题
当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"];
答案 0 :(得分:5)
首先,正如Sarke所提到的,在DB中存储文件内容并不是最好的选择(文件元数据完全不同。
为什么呢?
我存储了近200万张图像,这些图像存储在一个简单的文件夹结构中:/xx/yy/filename
,其中filename =文件的md5(+可选的数字应该发生哈希冲突),xx = md5的前2个字符, yy = md5的第3和第4个字符。它工作得很好,我不应该长时间得到任何FS相关的减速(至少2个数量级)。
回到你的问题有3个选项
max_allowed_packet
将图片大小限制为~8 MB,mediub_blob
最多可以存储16 MB。要对此进行排除,请将max_allowed_packet
增加到32 MB并进行测试。您需要确保在任何时候都没有超过此尺寸的图片,并确保应用程序在上传照片时能够正常工作。如果你能找到一个上传并且显示得很好的图像(来自DB!),后来却没有,那么这不是原因。答案 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
触发器可以让您确切知道问题何时发生,并可能有助于识别可能的模式。比较OLD
和NEW
值并在日志表中记录尽可能多的相关可用数据 - 注意,比较大型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