5

Piszę oprogramowanie synchronizujące, które zajmie wszystkie zmiany w jednym DB i zsynchronizuje je z innym DB. W tym celu Dodałem w moim stole T dwóch kolumnach:Czy istnieje możliwość wyścigu w instrukcji UPDATE?

alter table T add LastUpdate rowversion, LastSync binary(8) not null default 0 

Teraz mogę łatwo wybrać wszystkie wiersze, które zostały zmienione od czasu ostatniej synchronizacji:

select * from T where LastUpdate > LastSync 

Jednak po przeprowadzeniu synchronizacji Powinienem uczynić dwa pola równymi. Ale aktualizacja wiersza aktualizuje także znacznik czasu, więc muszę to zrobić:

update T set [email protected]@DBTS+1 where [email protected] 

Ale zastanawiam się - czy to zawsze zadziała? Co się stanie, jeśli odczytam wartość @@DBTS, a następnie inny użytkownik zdoła wstawić/zaktualizować wiersz gdzieś przed zatwierdzeniem mojego wiersza? Czy to ryzykowny kod? A jeśli tak, to w jaki sposób można go ulepszyć?

+0

Przy okazji, w jakiej wersji i wersji programu SQL Server jesteś? Czy opcja [Zmień dane przechwytywania] (http://msdn.microsoft.com/en-us/library/bb522489.aspx) jest opcją? –

+0

@Martin Smith - 2008, myślę. Nie wiem, co klient ma. –

+0

@Martin Smith - Sprawdziłem przechwytywanie danych zmian, ale to byłaby przesada. Wystarczy prosty znacznik czasu. Muszę tylko wiedzieć, które rekordy muszą zostać zsynchronizowane. Nie potrzebuję pełnej historii. –

Odpowiedz

-1

Jeśli uruchomisz to w transakcji Serializable, żadne inne operacje odczytu/zapisu nie będą mogły wpływać na te tabele.

RepeateableRead może również wykonać zadanie ...

+1

Tabele - tak. Ale co z wartością '@@ DBTS'? To nie jest przechowywane w żadnej tabeli! –

+0

@Vilx Jeśli weźmiesz wyłączną blokadę tabeli na czas trwania synchronizacji, to prawdopodobnie nie ma znaczenia, że ​​'@@ DBTS' zostanie zwiększone o zdarzenie w innej tabeli. –

+0

@Martin Smith - ale @@ DBTS jest globalna dla całego DB. Dlaczego to nie ma znaczenia? Jeśli otrzymam jedną (starszą) wartość dla pola 'LastSync' i nowszą dla pola' LastUpdate', moja synchronizacja zostanie zerwana. –

4

Przechowywanie „LastSync” w tej samej tabeli jako prawdziwy danych nie jest może dobrym pomysłem w ogóle. Spróbuj zapisać go w innej tabeli, która nie ma rowwersji. W ten sposób unikasz "aktualizacji wiersza aktualizuje również znacznik czasu" - problem.

Oprogramowanie synchronizator może wtedy działać w ten sposób:

  • uzyskać wartość @LastSync z dodatkowym stołem
  • "Wybierz @ThisSync = max (LastUpdate) z T gdzie LastUpdate> @LastSync"
  • "Wybierz * z T, gdzie LastUpdate> @LastSync i LastUpdate < = @ThisSync" to twoje wiersze do synchronizacji
  • Zapisz @ThisSync jako nowy "LastSync" w dodatkowej tabeli.

Wpisy zmodyfikowane w trakcie synchronizacji będą miały wyższą wartość rowversion niż zapytanie max(). Zostaną zsynchronizowane przy następnym wywołaniu synchronizatora.

+0

To jest pomysł. Będę o tym pamiętał, na wypadek gdyby nie było nic lepszego. –

Powiązane problemy