2012-06-13 11 views
5

W tabeli typu mysql MyISAM wpisz kolumnę Image typu mediumblob i zapisz przechwycony obraz. Mam ciekawe i problematyczne obrazy. Niektóre obrazy są danymi gradually losing.Dane obrazu MySQL BLOB stopniowo tracą?

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

my.ini max allowd rozmiar pakietu ustaw max_allowed_packet = 8M

image1 image2 image3

to jest problem

Kiedy C# aplikacja pobierania danych z serwera za każdym razem tego rodzaju obrazu s tracąc dane stopniowo i losowo. Mam złe obrazy takie jak te w 100000+ danych.

Co może być przyczyną takiego zachowania? Każdy ma jakiś pomysł/rozwiązanie, jak naprawić/uniknąć tego problemu.

aktualizacji 1:
Reading bajtów postać 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(); 
}   

Zapisywanie szereg bajtów na bazie danych jako nośnik danych blob. Podczas pobierania danych z bazy danych Jestem odlewania dane czytnika

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

Jeśli przechowujesz obrazy w bazie danych, będziesz miał zły czas. Dlaczego nie przechowywać ich jako zwykłych plików? – Sarke

+0

@niksonkantiPaul Jestem po prostu ciekawy, dlaczego zapisać obraz do DB, a nie tylko ścieżkę i obraz do folderu? – jcho360

Odpowiedz

4

Culprit to typ pamięci MyISAM.

Użyliśmy pamięci InnoDB do przechowywania miliona obrazów i przeprowadzonego testu warunków skrajnych, uzyskaliśmy właściwe wyniki. Plik został pobrany poprawnie lub w ogóle nie został pobrany (mniej niż 0,01%), ponieważ InnoDB jest zgodny z kwasem.

Kiedy przenieśliśmy się do MyISAM, wskaźnik awaryjności wzrósł do 20% ze stratnymi danymi, podobnie jak w przypadku.I powód był taki, że MyISAM używa blokady tabeli, więc podczas gdy zapis jest w toku cała tabela jest zablokowana, a w przypadku przekroczenia limitu czasu nadpisuje coś, co prowadzi do utraty danych.

Teraz przenieśliśmy wszystko do MS SQL, ponieważ InnoDB działa dobrze, ale wciąż nigdy nie korzysta z usuniętego obszaru plików, więc InnoDB nieustannie rośnie. MS SQL express ma limit 10 gb, więc stworzyliśmy strony 4-8 gb i tam przechowujemy bloby. Mamy też własną niestandardową replikację do replikacji plików na trzech serwerach w sieci z tą samą konfiguracją.

Przechowywanie plików na dysku jest z wielu powodów złe, ponieważ wszyscy mówią, że systemy plików są zaprojektowane pod kątem wysokiej wydajności i mogą przechowywać miliony plików, nie jest to prawdą, dyski nie działają szybciej, gdy masz ponad 100 tysięcy plików . Działają dobrze z jednym dużym plikiem, a następnie z 1000 mniejszymi plikami. Obecnie przechowujemy 10 milionów plików i przechowywanie ich w bazie danych ma większe znaczenie, ponieważ db wykonuje optymalizację za pomocą kwerendy i wykonuje dobre buforowanie. Więcej informacji można znaleźć pod adresem http://akashkava.com/blog/127/huge-file-storage-in-database-instead-of-file-system/

Jest to dokładny powód, dla którego wynaleziono MongoDb, Hadoop, Azure Blob Store, Haystack i Amazon S3.

5

Przede wszystkim, jak już wspomniano Sarke, przechowywanie plików zawartość w DB nie jest najlepszym pomysłem (plik meta dane to zupełnie inna historia.

Dlaczego

  1. Wydajność:?. w większości cache przypadki OS plik będzie wyprzedzić niczego wbudowana w DBMS
  2. odzyskiwania
  3. Disaster: kursy tracąc wszystkie/większość plików na uszkodzenia są o wiele wyższe niż w przypadku systemu plików i odzyskiwanie jest znacznie trudniejsze
  4. Skalowanie: jeśli przerosniesz pojemność pojedynczego serwera, dodanie shardingu na poziomie aplikacji jest banalne i nie ma kary za wydajność. Nastawienia multiserver DB są bardziej „bolesne”
  5. Wiele dostępnych rozwiązań/łatwość migracji: Jest wiele sprzętowe i programowe rozwiązania dla dużych przechowywania zbiorów plików i migracji między nimi jest znacznie bardziej proste niż migracji pomiędzy DBMS

I przechowuj blisko 2 miliony obrazów przechowywanych w prostej strukturze folderów: /xx/yy/filename, gdzie nazwa pliku = md5 pliku (+ opcjonalna liczba w razie kolizji mieszania), xx = pierwsze 2 znaki md5, yy = 3 i 4 znak md5 . Działa wspaniale i przez dłuższy czas nie powinienem mieć żadnych spowolnień związanych z FS (przynajmniej 2 rzędy wielkości).

Wracając do Twojego pytania są 3 opcje

  1. Pliki nie są poprawnie zapisane do DB. Może to być problem w aplikacji, która przesyła zdjęcia lub obraz jest zbyt duży.Twój rozmiar ogranicza rozmiar obrazu do ~ 8 MB, mediub_blob może pomieścić maksymalnie 16 MB. Aby rządzić tym zwiększeniem o max_allowed_packet do 32 MB i przetestuj. Musisz upewnić się, że żaden obraz nie przekroczy tego rozmiaru w dowolnym momencie i upewnić się, że aplikacja prawidłowo wykonuje swoje zadania podczas przesyłania zdjęć. Jeśli znajdziesz obraz, który został załadowany i wyświetlony w porządku (od DB!), A później nie, to nie jest przyczyną.
  2. Pliki zostają uszkodzone podczas aktualizacji - jeśli coś zaktualizuje zdjęcia w jakikolwiek sposób, nawet jeśli oryginalny plik jest w porządku, zaktualizowany może nie być - może na przykład przekroczyć ograniczenia rozmiaru z punktu 1.
  3. (najmniejsza prawdopodobnie jeden) Jeśli plik jest przechowywany i aktualizowany bez uszkadzania go, to ulega uszkodzeniu podczas przechowywania -> bez zgłoszonych błędów MySQL na tym (i to nie pozostało niezauważone) Chciałbym spojrzeć na sprzęt serwera.
+0

1. nie częściowe pisanie 2. uszkodzenie jest trwałe, –

+0

Tylko po to, aby upewnić się: potwierdziłeś, że zdjęcia były w porządku (pobrane co najmniej raz nieuszkodzone z DB) i dopiero później odkryli, że są teraz uszkodzone? – c2h5oh

+0

tak, ale nie tak często –

2

Wydaje mi się, że najpierw trzeba ustalić, czy to aplikacja, czy też proces zewnętrzny (tworzenie kopii zapasowych/przywracanie?), Który zmienia te dane. W rzeczywistości nie widzę powodu, dla którego aplikacja musiałaby aktualizować ten obraz (to znaczy aktualizować pole tymi samymi danymi), jeśli plik ma pozostać niezmieniony.

Po znalezieniu części aplikacji aktualizujących to pole, możesz opublikować kod, aby sprawdzić, czy nie ma konwersji, ucieczki lub cokolwiek innego.

Jeśli, jak przypuszczam, taka aktualizacja nigdy nie powinna się zdarzyć, ustawienie wyzwalacza BEFORE UPDATE na stole pozwoli ci dokładnie określić, kiedy wystąpi problem, i może pomóc w zidentyfikowaniu możliwego wzoru. Porównaj wartości OLD i NEW i zapisz jak najwięcej istotnych dostępnych danych w tabeli logów - uważaj, porównując duże obiekty BLOB możesz być zabójcą wydajności, uważnie obserwować swoje występy.

0

Jakiego API używasz do pobierania danych z bazy danych? Zdobądź kod, który pobiera dane.

Zwykle BLOB-y są odczytywane z bazy danych za pomocą pewnego rodzaju "przesyłania strumieniowego", więc może trzeba będzie przełączyć się na coś solidniejszego niż ADO.NET, jeśli go używasz.

Ta strona może być przydatna: http://dev.mysql.com/doc/refman/5.5/en/connector-net-programming-blob.html

1

Moja firma zdecyduje się na przechowywanie obrazów poza bazą danych. Zauważyliśmy, że Blobs, podobnie jak ten, którego używasz, są podatne na problemy z korupcją i wydajnością. Widzieliśmy te same problemy w MSSQL, Sybase i Faircom.

Ilekroć aplikacja potrzebuje dostępu do obrazu, potrzebuje dostępu do pamięci sieciowej (lub sieciowej), w której może znaleźć to zdjęcie. Następnie dane przechowują tylko ścieżkę do obrazu.

Ponieważ obraz jest płaskim plikiem gdzieś w systemie plików, jeśli rekord musi zostać zaktualizowany (tj. Notatką dodaną do opisu obrazu), obraz, w którym się znajduje, nie jest ponownie kompilowany do obszaru typu blob, a tam nie ma szans na to, że zostanie zepsuty.

+0

dlaczego to się dzieje wielokrotnie w tym samym obrazie :(, –

+0

Czy Twój program kiedykolwiek ponownie zapisał rekord (w tym pole Blob)? – CEPA