Synchronizacja danych sqlite

0

Witam wszystkich forumowiczów.

Mam takie pytanie odnośnie synchronizacji baz danych sqlite.
Mamy bazę danych historical_data_2014_11.db za pomocą np :rsync robimy kopię na zdalny serwer, powiedzmy, że baza zajmuje 20Mb. Następnie chcemy zrobić ponowną synchronizację za ok 5min. Po tym czasie baza zmieniła rozmiar do 25Mb. Problem tkwi w tym, że rsync zgra całą bazę od nowa czyli całe 25Mb. A mi by zależało na tym aby wysłać ("dokleić") tylko tą część pliku która została zmieniona, czyli przesłać te 5Mb.
Pomocy !
Pozdrawiam

0

No ale to jest jakiś backup plików a tu chodzi o bazę danych która jest jednym plikiem.

Musisz poczytać o replikacji danych między bazami i nie jest to takie proste jak się wydaje.

0

Widzę, że kolega mnie nie zrozumiał. Nie chodzi mi tu o ładne kopiowanie plików w oddzielnych katalogach z każdego dnia.
Może wyjaśnię co chciał bym osiągnąć.
Mamy procesor ARM9, na nim pracuje system linux. Na tym systemie jest zainstalowana baza danych sqlite do której dane są dostarczane za pomocą programu w C z przetworników analogowo-cyfrowych. Bazy są tworzone co miesiąc historical_data_2014_11.db (po każdym miesiącu zajmuje ona ok 40Mb). Taką bazę z aktualnego miesiąca muszę przesłać na serwer na którym dane z tej bazy są prezentowane w postaci diagramów, wykresów raportów. Zapisy do tej bazy są co minutę, a ja muszę ją przesyłać co 5 minut. Gdy rozmiar bazy mieści się w granicach 40Mb czas przesyłania zajmuje powyżej 1 minuty co blokuje w tym momencie zapis. Gdyby istniał mechanizm pozwalający na kopiowanie tylko tej części bazy która uległa zmianie to problem by się rozwiązał.
Czyli musiał bym na ARM9 odciąć zmienioną część pliku .db a na serwerze je "skleić".

Albo inaczej może nie korzystać w tym przypadku z rsync ale np: sprawdzać jakie definicje INSERT były wykonane i je tylko przesyłać i wykonywać na zewnętrznym serwerze ? Tylko jak ?
Może są jakieś inne metody wam znane ?
Nie oczekuję tutaj gotowego rozwiązania tylko nakierujcie mnie jakoś na właściwą drogę i rozwiązanie.

0
MiL napisał(a):

No ale to jest jakiś backup plików a tu chodzi o bazę danych która jest jednym plikiem.

Musisz poczytać o replikacji danych między bazami i nie jest to takie proste jak się wydaje.

Z tego co wiem to SQLite nie ma mechanizmu replikacji.

0

Synchronizacja przyrostowa raczej odpada. SQLite oprócz dopisywania nowych danych do pliku zapewne modyfikuje także nagłówki, więc później może być problem.
Najprościej chyba będzie jeśli po prostu zrobisz kopię pliku, wyślesz ją na serwer docelowy a później usuniesz. Zrobienie kopii 40mb pliku raczej nie powinno zablokować zapisu.

0
d20alien napisał(a):

Z tego co wiem to SQLite nie ma mechanizmu replikacji.

Nie ma i właśnie dlatego to nie jest takie proste bo trzeba ją sobie napisać samemu.

@d20alien
Musisz przesyłać na serwer tylko te dane które się zmieniły, nie możesz przesyłać całego pliku bazy danych a tym bardziej jego części.
Proponowałbym dodać do tabel które przesyłasz znacznik czasu utworzenia rekordu i przesyłać tylko te rekordy które się zmieniły lub doszły od ostatniej wysyłki.
Musisz to zrobić na poziomie pojedynczego rekordu.

0

@d20alien przeczytaj swój pierwszy i ostatni post - to co jest w ostatnim powinno się znaleźć w pierwszym

To może w ten sposób:

  1. baza główna - dane.db
  2. baza do exportu - exportXXX.db, gdzie XXX to jakiś unikalny ciąg - np. data i godzina
  3. program zapisuje jednocześnie do dwóch baz. Do bazy głównej bez zmian, do bazy dodatkowej tak
    a) sprawdza czy da się ją otworzyć
    b) jak tak to otwiera i zapisuje
    c) jak nie to tworzy nowy plik z bazą i od teraz jego traktuje jak dodatkowy
  4. program zgrywający dane na serwer operuje tylko i wyłącznie na tych dodatkowych bazach - jak chce pobrać to blokuje plik, dane cząstkowe importuje na serwer do jednej bazy a potem usuwa plik z tą dodatkową bazą
1

Trochę karkołomne rozwiązanie. Ja bym nowe rekordy odczytywał z bazy i zapisywał do pliku, plik wysyłał na serwer i tam tylko INSERT do bazy na serwerze.

0

tylko, że poleganie na timestampach w bazie może okazać się złym pomysłem - wystarczy, że zmieni się czas na komputerze i albo będą zduplikowane rekordy albo którychś nie będzie. Pewnym rozwiązaniem było by oznaczanie, które zostały wyeksportowane ale to wiąże się z dostępem do bazy przez dwie różne aplikacje, które będą chciały coś w niej zmieniać a tego sqlite nie przewiduje.

0
MiL napisał(a):

Trochę karkołomne rozwiązanie. Ja bym nowe rekordy odczytywał z bazy i zapisywał do pliku, plik wysyłał na serwer i tam tylko INSERT do bazy na serwerze.

Podoba mi się ten pomysł. Tylko może tak jak kolega wyżej się wypowiedział nie opierać się na timestamp tylko na id ?
Pobieram z bazy dane sprawdzam, czy id jest większe od tego który mam zapisany z poprzedniej synchronizacji.
Dane pobierał bym zaraz po INSERCIE czyli jak INSERT jest w 1 minucie to SELECT będzie w 1min i 30sek ?
W tej bazie historical_data_2014_11.db jest wykonywany tylko INSERT nie ma żadnych UPDATE, więc może ta metoda by się sprawdziła ?

0

To dodaj pole które będzie oznaczało status eksportu, nie opieraj się na ID. Po wyeksportowaniu ustawiaj tam np. 1 i wtedy wiesz że dany rekord już został wyeksportowany. Nie porzucałbym jednak pola z datą insertu bo w razie niepowodzenia eksportu zawsze możesz określić które po dacie które rekordy trzeba wysłać ponownie.
Ja dodałbym 3 pola: ExportStatus, InsertDate, ExportDate.
W zasadzie jeżeli ustawisz ExportDate to ExportStatus nie będzie potrzebny, czyli eksportujesz tylko takie rekordy które mają null w ExportDate.
Do wybory do koloru :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1