2012-06-13 77 views
5

在mysql MyISAM類型表中有一列Image類型mediumblob並存儲捕獲的圖像。我收到了一些有趣和有問題的圖像。一些圖像是gradually losing數據。MySQL BLOB圖像數據逐漸丟失?

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

my.ini最大allowd包大小設置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(); 
}   

保存字節陣列分爲數據庫作爲介質blob數據。從檢索數據庫中的數據。當我鑄造讀者數據

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

如果您將圖像存儲在數據庫中,您會有一段糟糕的時間。爲什麼不把它們存儲爲常規文件? – Sarke

+0

@niksonkantiPaul我只是好奇你爲什麼要將圖像保存到數據庫中,而不是將路徑和圖像保存到文件夾中? – jcho360

回答

4

罪魁禍首是MyISAM存儲類型。

我們使用InnoDB存儲來存儲一百萬張圖片並進行壓力測試,我們得到了正確的結果。由於InnoDB符合酸性標準,所以任何一個文件都可以正確檢索或者根本檢索不到(小於0.01%)。

當我們轉移到MyISAM時,失敗率增加到20%,有損數據也與您的情況相同。原因是,MyISAM使用表鎖,因此在寫入過程中,整個表被鎖定,如果發生超時,它會覆蓋導致數據丟失的內容。

現在我們已經把所有東西都轉移到MS SQL上了,因爲InnoDB性能良好,但它從不重複使用已刪除的文件空間,所以InnoDB不斷增長。 MS SQL express的限制爲10gb,所以我們創建了4-8gb的頁面,並且我們在那裏存儲了斑點。而且我們有自己的定製複製功能,可以通過同一配置的網絡在三臺服務器上覆制文件。

由於許多原因,在磁盤上存儲爲文件是不好的,大家一直說文件系統是爲高性能而設計的,可以存儲數百萬個文件,但事實並非如此,當您擁有超過10萬個文件時,驅動器無法執行得更快。它們在一個大文件和1000個小文件中表現良好。目前我們正在存儲1000萬個文件,並將其存儲在db中更有意義,因爲db對查詢進行了優化並進行了良好的緩存。你可以閱讀更多在http://akashkava.com/blog/127/huge-file-storage-in-database-instead-of-file-system/

這就是爲什麼發明MongoDb,Hadoop,Azure Blob商店,Haystack和亞馬遜S3的確切原因。

5

首先,作爲Sarke提到,存儲文件在數據庫的內容是不是最好的主意(文件元數據是一個完全不同的故事。

爲什麼

  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並進行測試。您需要確保任何時候沒有圖像超過這個尺寸,並確保該應用在上傳照片時是否正確。如果你能找到一張上傳並顯示的圖像(從數據庫!),然後它不會,這不是原因。
  2. 的文件更新過程中受損 - 如果有任何更新以任何方式照片那麼,即使原始文件是罰款更新的一個可能不是 - 這可能例如超過從點大小限制1.
  3. (最低可能是一個)如果文件存儲和更新時不損壞它,那麼它在存儲時會受到損壞 - >沒有報告的MySQL錯誤(這不會被忽視)我會看看服務器硬件。
+0

1.沒有部分文字 2.損壞是永久性的, –

+0

只是爲了確保:您已經確認圖像正常(從數據庫中至少讀取了一次數據)並且之後才發現它們已經損壞? – c2h5oh

+0

是的,但它沒有那麼頻繁 –

2

我想你首先需要弄清楚它是你的應用程序還是一些改變這些數據的外部過程(備份/恢復?)。 實際上,如果文件應該保持不變,我看不到爲什麼你的應用程序需要更新這張圖片(即用相同的數據更新字段)。

一旦您找到應用程序的哪些部分更新此字段,您可能需要發佈一些代碼以查看是否沒有轉換,轉義或其他任何事情發生。

如果我認爲這樣的更新永遠不會發生,那麼在表上設置一個BEFORE UPDATE觸發器將允許您確切地知道問題何時發生,並可能有助於識別可能的模式。比較OLDNEW值,並在日誌表中記錄儘可能多的相關可用數據 - 請注意,比較大型BLOB可能會成爲性能殺手,請密切關注您的表現。

1

我公司選擇存儲在數據庫之外的圖像。我們注意到,像您正在使用的Blob一樣,Blobs容易出現腐敗和性能問題。我們在MSSQL,Sybase和Faircom看到了同樣的問題。

每當應用程序需要訪問圖像時,它都需要訪問可以找到該圖像的網絡(或基於Web的)存儲。然後數據只存儲圖像的路徑。由於圖像是文件系統某處的平面文件,因此如果記錄需要更新(即添加註釋以描述圖像),則它自身的圖像不會重新編譯到blob中,並且在那裏它沒有被損壞的機會。

+0

然後爲什麼它在相同的圖像中重複發生:(, –

+0

您的程序是否重新寫入記錄(包括Blob字段)? – CEPA