C# Synchronizacja bazy lokalnej i online

Cześć wszystkim - mam problem,

piszę program, który będzie posiadał w sobie wbudowaną bazę danych (lokalną - offline) dla pracowników danej firmy.

W momencie gdy taki pracownik kliknie przycisk “aktualizuj” to baza danych offline ma się zsynchronizować z tą bazą danych na serwerze tzn. wysłać dane które zostały zmienione, dodane w bazie lokalnej i pobrać te, które ktoś zmienił w bazie online.

Chodzi o to abym w bazach lokalnych miał to samo co w bazie online - po kliknięciu przycisku aktualizuj.

Zastanawiam się zatem, jak zrobić pobieranie do bazy lokalnej rekordów nowo utworzonych, zmodyfikowanych oraz w jaki sposób usuwać rekordy.

Baza danych online to MySQL, natomiast baza lokalna to Access … - ale problem rozwiążę chyba wprowadzając dodatkową kolumnę w każdej tabeli informującej o ostatniej modyfikacji.

Chcę to zrobić w możliwie łatwy sposób, ale tak aby baza danych się nie zapychała… - tzn. rozumiem, że najszybciej byłoby aby w momencie gdy ktoś kliknie “aktualizuj” cała baza danych online była pobierana do online - ale w przypadku dużej liczby rekordów będzie to niepotrzebny balast.

Myślę, że można to zrobić wprowadzając do tabel w bazie danych dodatkowe kolumny informujące o tym, czy jakiś rekord był modyfikowany - a jeżeli był to kiedy (na tej podstawie baza online ściągnie, albo nie dany rekord) …

No dobrze, pokażę na przykładzie o co mi chodzi :

Załóżmy, że mamy dwóch pracowników (ich liczba może być większa) - każdy pracownik i baza online ma taką samą strukturę (chyba, że coś zmienić co mi pomoże np. dodać nową kolumnę to piszcie…).

Baza danych poniżej - jest aktualna, tzn te same dane znajdują się w każdej bazie lokalnej i bazie online :

t727864_baza-danych.jpg

- Dodawanie nowego rekordu :

Załóżmy, że pracownik 2 będzie chciał utworzyć nowy rekord, jak pobrać tylko ten nowo utworzony rekord przez pracownika 1 ? Co w momencie gdy pracownik 1 także będzie chciał utworzyć nowy rekord - zakładam, że wszystkie operacje są wykonywane na bazie offline - dopiero w momencie aktualizacji pracownik przesyła dane do bazy online.

t727870_baza-danych.jpg

Zakładając, że pole ID będzie to klucz główny - nowe rekordy mogę rozpoznawać w ten sposób, że zrobię zapytanie SELECT do bazy online o wszystkie rekordy których ID jest większe niż największe w bazie offline.

Tzn. - Select * from pracownicy where id 3

W tym przypadku jeżeli baza danych mi coś zwróci - oznacza to, że ktoś dodał nowe rekordy.

No dobrze, ale co w przypadku gdy pracownik 1 będzie chciał także utworzyć nowy rekord przed aktualizacją bazy danych tzn.

t727871_baza-danych.jpg

Numer ID nowego rekordu będzie taki sam w bazie offline pracownika 1 i pracownika 2.

Co w tej sytuacji zrobić - jak pogodzić tworzenie nowych rekordów offline - kto pierwszy doda rekord ten lepszy …?

I w momencie gdy przy dodawaniu rekordu przez pracownika1 wyskoczy błąd (Id istnieje), to zmienić id na największy możliwy (musiałbym to zrobić także ze wszystkimi powiązaniami w bazie offline, które dotyczyły tego rekordu)…

- modyfikacja

Problem dodawania nowych rekordów, nie jest taki ciężki - cięższe wydaje mi się sprawdzanie czy coś zostało modyfikowane.

t727899_baza-danych.jpg

Załóżmy, że pracownik 2 będzie chciał zmienić rekord 2 i zaktualizuje go w bazie danych online - zmienione pole to nazwisko - przy czym, gdzie rekord jest modyfikowany to zmieniam także pole data M (data modyfikacji)…

I teraz w jaki sposób ma to odczytać pracownik1, że coś w bazie online różni się od tego co on posiada ?

Przecież nie będę robił zapytania w postaci czy data modyfikacji 1 rekordu offline == data modyfikacji 1 rekordu online, czy data modyfikacji 2 rekordu offline == data modyfikacji 2 rekordu online …

W ten sposób do bazy danych musiałbym wysłać tyle zapytań ile mam rekordów - a to wydaje mi się ( nie jestem pewien) może zapchać bazę danych…

Może zapytanie skonstruować w ten sposób, że z bazy offline wybiorę ostatnią datę modyfikacji i sprawdzę czy jest jakaś data w bazie online “później” od tej daty tzn.

zapiszę sobie najnowszą datę modyfikacji bazy offline pracownika 1 (w tym przypadku) 15-stego

Select * from pracownicy where data_M 15

W wyniku powinienem dostać rekordy, których nie mam zaktualizowanych w bazie danych tzn. utworzone po 15 i zmodyfikowane … czyli nie musiałbym w tym przypadku szukać rekordów nowych - czy dobrze myślę ?

Właśnie to przemyślałem i chyba nie ma tak prosto - bo jak wcześniej pisałem, programy pracują na bazie offline i w momencie kliknięcia aktualizuj łącza się online - więc pracownik1 pracując offline może też w międzyczasie (przed aktualizacją bazy) dokonać jakiejś modyfikacji w dniu późniejszym np.:

t727923_baza-danych.jpg

I teraz w momencie, gdyby pracownik1 chciał zaktualizować bazę w w/w sposób dokonałby tego dla

Select * from pracownicy where data_M 25 - czyli nie zobaczyłby zmodyfikowanego rekordu z dnia 19 !!

Jak sobie z tym poradzić …?

W jaki sposób skonstruować zapytanie - może dodać jakieś pole do tabeli, które będzie pamiętało coś innego…?

Pozostaje jeszcze kwestia usuwania - jak to zrobić, jeżeli np. pracownik2 usunie rekord1 - nie może go raczej usunąć z bazy online, gdyż w ten sposób pracownik 1 nie dostanie informacji o tym że taki rekord ma być usunięty…

Myślę, że wiecie już o co chodzi - chce za pomocą dodatkowych kolumn w tabeli skonstruować synchronizację baz danych - tak aby były przechowywane informacje o tym czy coś zostało zmodyfikowane itp…

Prosiłbym o pomoc

Może byłby ktoś w stanie mi to rozrysować, albo opisać tak abym zrozumiał.

Dziękuję za pomoc :wink:

Wszystko zależy od danych jakie będzie przechowywać baza oraz w jaki sposób mają z niej korzystać użytkownicy. Jeśli mają tylko dodawać do bazy to żaden problem, jeśli będą dodawać i usuwać da się obejść, jeśli będą do tego edytować wiersze to masz problem. Wyobraź sobie sytuacje że jeden i drugi użytkownik edytuje lokalnie ten sam wiersz w tabeli, teraz robisz aktualizacje bazy online, którą edycję przyjmiesz za ostateczną? Z kolei jeżeli po każdej zmianie stanu bazy, zmiany mają być widoczne dla każdego, to czemu nie zastosować jednej bazy danych online? Napisz jeszcze jak często szacujesz klikanie w tą aktualizacje? Raz na dzień? Tydzień? Czy przed/po każdym rozpoczęciu pracy z danymi?

Microsoft udostępnia technologię, która ma pomóc (przynajmniej w teorii) w rozwiązaniu dokładnie takiego problemu jak Twój http://msdn.microsoft.com/en-us/sync/bb887608. Piszę w teorii, bo nie miałem jeszcze okazji z tego korzystać (chyba najwyższy czas się z tym zapoznać :slight_smile: ). Poza tym nie mam pewności, czy wspierane są podane przez Ciebie bazy danych (choć zapewne są). Zapoznaj się z tym i daj znać, czy to rozwiązuje Twój problem. Jeśli z jakiegoś powodu nie (jakiego?), to się pomyśli dalej.

Właśnie ten problem starałem się też pokazać powyżej :wink:

Może ktoś ma jakiś sensowny pomysł jak sobie z tym poradzić… zawsze ktoś musi pierwszy zaktualizować bazę online. W przypadku połączenia z bazą online przed zatwierdzeniem modyfikacji, pobiorę ten rekord z bazy i sprawdzę czy nie był on modyfikowany -> jeżeli nie był to go nadpiszę, a jeżeli był (taki przypadek jak opisujesz) to zapytam użytkownika, którą wersję chce zostawić tzn. czy pobrać ten rekord do siebie, czy zapisać swój na ten co jest…

Chodziło mi tutaj o to, że zmiany mają być widoczne w bazie offline w momencie gdy ktoś kliknie przycisk “aktualizuj” wtedy ściągnie najnowszą wersję bazy danych z serwera online.

Zakładam, że pracownicy mogą mieć brak połączenia z internetem - stąd konieczność pracy offline…

Myślę, że raz - 2 razy dziennie będzie baza aktualizowana - tzn. użytkownik kliknie przycisk aktualizuj.

Matzu - gdzieś kiedyś czytałem o Microsoft Sync, ale nie wiem jak to wdrożyć - żadnych ciekawych opisów nie znalazłem, myślę jednak że łatwiej będzie na dodatkowych kolumnach tak jak to opisałem.

Skoro proponujesz takie podejście do sprawy to zakładam że użytkownicy nie wymagają ciągłej spójności z główną bazą danych, ale ponieważ nie mam pojęcia o jakiej w ogóle dziedzinie dyskutujemy nie jestem w stanie nic zaproponować na edytowanie tego samego wiersza przez kilku użytkowników. Jeśli chodzi o synchronizowanie baz, to tak będziesz musiał dodać daty ostatniej modyfikacji. W bazie lokalnej będziesz przechowywał czas ostatniego rozpoczęcia pobierania danych z bazy online. Każdą aktualizację rozpoczniesz od dodania nowych wierszy z bazy lokalnej, a więc zostaną im przydzielone czasy modyfikacji późniejsze niż czas ostatniego rozpoczęcia pobierania danych z bazy online. Następnie przechodzisz do pobierania, zapisujesz nowy czas rozpoczęcia pobierania (stary przechowujesz jakby aktualizacja się nie powiodła). Następnie pobierasz wszystko co ma datę modyfikacji późniejszą niż czas ostatniego rozpoczęcia pobierania.

Pobierzesz też wiersze które niedawno sam do bazy wysłałeś ale wrócą już do Ciebie z globalnymi indeksami. Teraz jeszcze pytanie kto ma być odpowiedzialny za indeksowanie wierszy w tabelach bazy globalnej? Najlepiej zrobisz jak postawisz dodatkową warstwę abstrakcji, serwer który udostępni Ci potrzebny interfejs, dostęp do bazy online będzie tylko przez serwer. Założysz wtedy zamki na edytowanie wierszy, unikniesz sytuacji kiedy:

user1 czas ostatniego rozpoczęcia pobierania danych 11:15

user2 czas ostatniego rozpoczęcia pobierania danych 11:40

wiersz w tabeli czas ostatniej modyfikacji 10:00

Tak więc user1 oraz user2 mają ten sam wiersz w swojej lokalnej bazie, obaj dokonają na nim edycji, a na następny dzień będą w mniej więcej tym samym czasie chcieli dokonać aktualizacji bazy. Zajmą się najpierw dodaniem nowych danych, a później aktualizacją wierszy które zmodyfikowali. Chcesz informować użytkownika że wiersz który próbuje zaktualizować już został przez kogoś innego zaktualizowany, oraz czy chce go nadpisać. Żeby tego dokonać musisz pobrać wiersz z bazy, a więc obydwaj użytkownicy pobierają ten sam wiersz, widzą że data modyfikacji jest 10:00, czyli nikt nie zmienił wiersza od czasu ostatniego pobrania danych, więc obydwoje wysyłają aktualizacje wiersza nie pytając o nic użytkownika. Jeden nadpisze drugiego i nikt nie będzie wiedział co i kiedy się stało.

Jeśli zrobisz sobie do tego serwer, wtedy user1 zapyta się o wiersz, serwer doda go sobie do listy czekającej na edycje. Nie wyśle wiersza drugiemu użytkownikowi dopóki pierwszy nie dokona aktualizacji.

Zachowanie pełnej spójności baz nie będzie takie proste jak Ci się wydaje, chyba że poświęcisz wydajność i zastosujesz system “wielu czyta - jeden pisze”.

Rozumiem, no ja niestety żadnych sprawdzonych źródeł na ten temat Ci nie dam.

Jeśli po stronie klienta będzie tylko jedna tabela, to faktycznie nie będzie tutaj wielkiej filozofii. Choć ja bym dał dwie kolumny po stronie klienta i po stronie serwera, tj. “Data utworzenia” oraz “Data ostatniej modyfikacji”. Po stronie klienta dodatkowo przyda się pole “Data ostatniej aktualizacji”. No problem może być taki, że w lokalnej bazie danych będziesz miał nowe rekordy oznaczone takim samym ID jak nowe rekordy w bazie danych serwera. Da się to oczywiście rozwiązać :slight_smile: W końcu te nowe ID w bazie klienta należy traktować jako tymczasowe.

Klient pobiera rekordy, które zostały zmodyfikowane w bazie danych serwera:

a) wstawione (INSERT): “Data utworzenia” (po stronie serwera) > “Data ostatniej aktualizacji” (po stronie klienta)

b) zaktualizowane (UPDATE): “Data ostatniej modyfikacji” (po stronie serwera) > “Data ostatniej aktualizacji” (po stronie klienta)

c) usunięte (DELETE): wyciągamy jakich ID, które są po stronie klienta, brakuje po stronie serwera (przy czym trzeba wykluczyć te, dla których “Data utworzenia” (po stronie klienta) > “Data ostatniej aktualizacji” (po stronie klienta), bo są to po prostu nowe rekordy w lokalnej bazie danych).

Klient pobiera rekordy, które zostały zmodyfikowane w lokalnej bazie danych:

a) wstawione (INSERT): “Data utworzenia” (po stronie klienta) > “Data ostatniej aktualizacji” (po stronie klienta)

b) zaktualizowane (UPDATE): “Data ostatniej modyfikacji” (po stronie klienta) > “Data ostatniej aktualizacji” (po stronie klienta)

c) usunięte (DELETE): wyciągamy jakich ID, które są po stronie serwera, brakuje po stronie klienta (przy czym trzeba wykluczyć te, dla których “Data utworzenia” (po stronie serwera) > “Data ostatniej aktualizacji” (po stronie klienta), bo są to po prostu nowe rekordy w bazie danych serwera).

Jeśli jednak tych tabel będzie więcej niż jedna w lokalnej bazie danych, to ta jedna kolumna, o której mówiłeś, nie wystarczy. Może przykład … Operacja UPDATE w jednej tabeli może być zależna od operacji INSERT w innej tabeli (taki zależności jest więcej, bo dana operacja INSERT też może być zależna od innej operacji INSERT). Teoretycznie mógłbyś sortować po kolumnie “Data modyfikacji”, ale co jeśli ten rekord, który był niedawno wstawiony zostanie jeszcze zmodyfikowany? “Data modyfikacji” rekordu przeznaczonego do operacji UPDATE będzie starsza niż tego do operacji INSERT i tym samym operacja UPDATE się nie powiedzie. Innymi słowy potrzebujesz tabeli (tak mi się wydaje), która będzie śledzić zmiany we wszystkich tabelach. Mogłaby mieć kolumny ID rekordu, ID tabeli (jakiś słownik), Rodzaj operacji (słownik - INSERT/UPDATE/DELETE), Data modyfikacji. Mając taką tabelkę nie zgubisz żadnej zmiany. Pytanie jak rozwiązać sytuację, gdy klucz główny w danej tabeli jest na kilku kolumnach lub gdy operacja Delete na jednej tabeli pociąga za sobą operacje Delete na kilku innych tabelach lub kilku innych rekordach danej tabeli :slight_smile: No i pytanie co zrobić w sytuacji, gdy użytkownik np. najpierw doda nowy rekord w lokalnej bazie danych, a zaraz potem go usunie. Skutkiem tego będą dwa wpisy w tej tabeli, czyli dwie operacje, które na bazie danych serwera nie powinny zostać wykonane. Trzeba by też pomyśleć co zrobić, gdy użytkownik kilka razy wykona Update na danym wierszu. Będzie to oznaczać kilka wpisów w tej tabeli. Wydaje mi się, że wystarczy jak wykonany zostanie ten najmłodszy, ale pytanie czy czegoś nie przeoczyłem :slight_smile: W każdym bądź razie ta tabela mogłaby być czyszczona co jakiś czas.

Poza tym niezbędne jest ustalenie, które dane mają priorytet (i tu znowu, tak mi się wydaje). Na starcie zarówno dane po stronie serwera, jak i po stronie klienta są spójne, tzn. są zgodne z obowiązującymi więzami integralności. Jeśli zaczniesz sobie robić tak, że w trakcie operacji aktualizacji część danych będziesz brał od klienta, a część od serwera, to się to wszystko pewno po jakimś czasie rozjedzie. Jeśli przykładowo przyjmiesz sobie, że priorytet mają dane z serwera (czyli innymi słowy jeśli przyjmiesz sobie, że nie obchodzi Cię praca danego klienta :twisted: i ważniejsza jest dla Ciebie praca wykonana przez innych klientów), to wówczas w sytuacji, gdy klient będzie chciał usunąć dany rekord, a serwer każe mu go zaktualizować, to po stronie klienta musi nastąpić aktualizacja, a nie usuwanie. Klient zostanie jednak poinformowany, że jego operacja usuwania została wycofana. Reasumując najpierw w danych lokalnych zostaną wprowadzone zmiany z serwera i tym samym zostanie sprawdzone, czy nie naruszają one więzów integralności, a następnie reszta zmian wprowadzonych przez klienta w jego lokalnej bazie danych (tych, które nie zostały nadpisane) zostanie wprowadzona na serwerze.

Jeżeli będą tego wymagali to będzie tutaj przycisk “aktualizuj” inaczej pracowaliby cały czas online :wink:

Chodzi o to, że użytkownik może być pozbawiony dostępu do głównej bazy przez jakiś czas…

EnterBioS odnośnie tego edytowania wierszy, to będę pamiętał datę i czas co do sekundy (chyba jest taka możliwość), więc podejrzewam że w tej samej sekundzie nie dojdzie do wrzucenia do bazy w tym samym czasie tego samego rekordu :wink:

Już sobie to troszkę rozplanowałem i wszystko można wykonać, tak żeby się zgadzało :wink:

Matzu - odnośnie identyfikatorów ID, to będą one zmieniane w bazie online - tymczasowo mają nadane numery ID w bazie offline, ale jeżeli online już są wiersze o takich ID to przed wstawieniem do bazy online zostaną one zmienione.

Wydaje mi się, że dodatkowej tabeli nie trzeba będzie używać … jeżeli ktoś kliknie przycisk aktualizuj to z bazy danych pobiorę wszystkie zmiany ze wszystkich tabel, które są potrzebne dla danego klienta (pracownika), oraz te które zostały dla niego wstawione.

Zmiany te zapiszę w bazie lokalnej (offline) na której będzie pracowała ta osoba.

Zresztą moje założenie jest takie, że tylko 1 osoba będzie mogła wstawiać nowe rekordy (centrala), natomiast wstawiony rekord będzie mógł modyfikować tylko pracownik (konkretny 1 ) i ewentualnie centrala.

Ale tak na zapas wolę się ubezpieczyć, gdyby edycję danego rekordu mogło wykonywać więcej pracowników …

I tutaj podałeś ciekawe zagadnienie - oczywiście w moim przypadku priorytetem będą dane przechowywane online tzn. jeżeli centrala usunęła online jakiś rekord, a pracownik go zaktualizował to przy następnej aktualizacji pracownika (jego rekord zostanie usunięty) - ale liczę tutaj na inną wymianę informacji (w ważnych przypadkach np. usunięcia rekordu centrala będzie starała się dopilnować aby pracownik dostał informację o usunięciu rekordu).

Czyli w zasadzie wszystko już masz przemyślane, czy jeszcze z czymś walczysz? Bo teraz trochę się zagubiłem.

Dziś zerknąłem, czy są w sieci jakieś ciekawe materiały na temat tego całego Sync Framework. Obejrzałem sobie ten godzinny filmik Introduction to Sync Services for ADO.NET and the Visual Studio Designer. Bardzo ciekawy. Daje obraz tego na co pozwala ten Framework (MySQL powinien bez problemu z nim współpracować) oraz jak go używać. Możesz też sobie przejrzeć, nawet jeśli teraz z niego nie skorzystasz.

Poza tym linki, które mogą się komuś przydać to:

Przykładowy kod -> Microsoft Sync Framework

Dokumentacja

Blog twórców

Jeszcze jedno pytanie - dość banalne - czy w przypadku jak pole klucz np. Id ustawie na autoincrement (aby się zwiększało) to mogę je także modyfikować ręcznie ?

Załóżmy, że w tabeli kolejne rekordy mają ID : 1,2,3,4 i teraz zmienię ręcznie 4 na 8 to czy kolejny dodany rekord z : 1,2,3,8 będzie miał ID 4 czy 9 ? I co w przypadku gdy usunę jakiś rekord, który miał pole ustawione na inkrementację

np. usunę z ID = 1,2,3,4 numer 3 i wtedy 4 zmieni się na 3, czy nadal pozostanie z id = 4 ?

Dzięki za informacje …

Bardzo bezsensowne byłoby zachowanie polegające na tym, że SZBD zmienia id encji. Powodowałoby to zmianę referencji, a w efekcie dane stały by się bezsensowne i przekłamane.

Normalne SZBD kolejnym rekordom nadają id o jeden większe od poprzedniego, zaś jeśli jakiś rekord został usunięty, to jest “dziura” w numeracji.

Czyli dobrze rozumiem - że jeżeli mam 1,2,3,4 to po usunięciu 4 i wstawieniu kolejnego rekordu będzie on miał id o numerze 5 ?

Co do zmiany id (klucz główny) to nie jest to takie bezsensowne :slight_smile: Załóżmy, że w bazie offline chciałbym uaktualnić ID takie jakie przyzna mu baza online po wstawieniu do niej nowego rekordu.

Gdyby się nie dało zmienić ID ręcznie - to najpierw w bazie offline musiałbym usunąć stary (rekord z niewłaściwym ID) i ściągnąć go jeszcze raz z bazy online. Czyli rozumiem, że nie można zmieniać ID (klucza głównego) ręcznie ?

Tak powinno się stać.

Sprecyzujmy - klucz główny, to po prostu kolumna (lub kilka kolumn) tabeli o specjalnym znaczeniu. Nie musi być liczbą, może być GUIDem lub ciągiem znaków. Klucz główny służy do jednoznacznej identyfikacji rekordów w tej tabeli, niczego więcej. A ponieważ to tylko kolumna, to Ty nadajesz jej wartości.

To, że SZBD nadaje wartości dla klucza głównego typu int automatycznie jest związane z dodatkowym atrybutem tej tabeli, zwanym być może identity być może autoincrement. Dzięki temu Ty nie musisz się martwić o nadanie dla nowego rekordu nowej, unikalnej liczby, zrobi to za Ciebie SZBD. Z tymże, włączenie na kolumnie tej automatyki powoduje, że nie można nadawać tych wartości ręcznie.

Zatem, jeśli chcesz mieć automatyczne nadawanie wartości klucza głównego, ale czasami móc je zmieniać, to przed tą zmianą trzeba najpierw wyłączyć autoincrement. Podejrzewam, że to może być dość niebezpieczne, gdy ktoś właśnie w tej chwili będzie chciał dodać nowy rekord z aplikacji, która będzie zakładała, że ID zostanie nadany automatycznie.

Aha, nie daję żadnej gwarancji, że to co napisałem dotyczy również MySQL. Ten produkt tworzony był pod hasłem “zróbmy coś co ma tabele, wiersze i kolumny, i zobaczmy ile osób nabierze się na to, że to baza danych”, więc nigdy nie wiadomo.

@desperado

Przy tym usuwaniu rekordu z danej tabeli bazy lokalnej musisz pamiętać o tym, że jeśli ta tabela zawiera klucz główny, który używany jest jako klucz obcy w innych tabelach (bądź nawet w tej samej tabeli) i na tym kluczu obcym ustawiony jest warunek ON DELETE CASCADE, to usunięcie rekordu z takiej tabeli spowoduje usunięcie powiązanego rekordu/rekordów z tych pozostałych tabel.

Dlaczego jest to ważne? Klient może np. wykonać INSERT to tabeli A, a zaraz potem INSERT do tabeli B, który jest zależny od poprzedniej operacji INSERT (rekordy powiązane relacją). Jeśli teraz wykonując operację na bazie zdalnej dodasz rekord do jej tabeli A, ale przy tym usuniesz też rekord z tabeli A w bazie lokalnej, to skończy się to tym, że utracisz informację o rekordzie wstawionym do tabeli B w bazie lokalnej. Musisz to jakoś uwzględnić. Nie nakażesz przecież klientowi dokonywać synchronizacji po każdym INSERT-cie w bazie lokalnej, bo było by to sprzeczne z założeniami tej aplikacji.