Synchronizacja dwóch baz danych w SQL Server

16

Mam dwie bazy danych SQL Server. Jeden to klient (aplikacja Windows), a drugi znajduje się na serwerze. Chcę synchronizować te dwie bazy danych tak często (np. Co 2 minuty!).

Czytałem o różnych sposobach synchronizacji, takich jak replikacja, znacznik czasu, tabele dziennika przy użyciu wyzwalaczy, Microsoft Sync Framework i tak dalej.

Właściwie nie lubię używać metody synchronizacji, która może być czarną skrzynką (jak replikacja), ponieważ nie chcę, aby tabele specyficzne dla SQL Server były blokowane podczas ich aktualizacji i synchronizacji z serwerem.

  1. jaką metodę według ciebie powinienem zastosować w takich okolicznościach? Pamiętaj, że co kilka minut muszę wysyłać kilka zmian tabeli z klienta na serwer i pobrać także dwie zmiany tabeli z serwera.

  2. Znalazłem metodę, która jest dziwna, ale nowa. Czy to możliwe, że rejestruję wszystkie wykonywane (dla określonych preferowanych) procedur przechowywanych w kliencie i wysyłam je wraz z parametrami do .sqlpliku na serwer i tam je wykonuję? To samo stanie się na serwerze i wysłane do klienta. Czy uważasz, że jest to prosta, ale przydatna metoda, czy nie?

  3. proszę zasugeruj mi jakieś użyteczne podejście, jeśli możesz. Dziękuję bardzo.

EDYCJA: Pamiętaj, że jest to synchronizacja w czasie rzeczywistym, co czyni ją wyjątkową. Oznacza to, że gdy użytkownik klienta korzysta z tabeli, proces synchronizacji z serwerem musi się odbywać co kilka minut, więc żadna z tabel nie musi być zablokowana.

Emad Farrokhi
źródło
1
Pamiętaj, że te „czarne skrzynki” są stosunkowo dobrze udokumentowane pod względem sposobu ich działania, sposobu ich konserwacji i monitorowania oraz tego, co możesz zrobić, aby naprawić je w typowych (i niezbyt powszechnych) scenariuszach awarii. Zastanowiłbym się nad wprowadzeniem własnej metody synchronizacji oraz koniecznością znalezienia i naprawienia błędów związanych z przypadkami brzegowymi, które „czarne skrzynki” rozwiązały dawno temu, i tylko wtedy, gdy miałem bardzo specyficzne potrzeby aplikacji (częściowa synchronizacja lub potrzeba użytkownika interaktywne rozwiązywanie konfliktów itd.).
David Spillett,
@DavidSpillett: Czy pomyślnie wykorzystałeś replikację w projekcie synchronizacji w czasie rzeczywistym? Moją główną troską jest synchronizacja w czasie rzeczywistym oraz „blokowanie i blokowanie”.
Emad Farrokhi

Odpowiedzi:

14

Cóż, może nie rozumiem, ale staram się na nie odpowiedzieć.

Powiedziałeś, że potrzebujesz wysokowydajnego rozwiązania, które często działa (minimum wszystkie 2 minuty) i potrzebujesz dobrego podejścia, które powinno być szybkie bez blokowania. Ale nie chcesz systemu blackbox.

Zamiast systemu blackbox, który jest używany w milionach instalacji z dobrymi wynikami, próbujesz wymyślić koło ponownie i zbudować własne rozwiązanie? Hm, brzmi trochę dziwnie.

W rzeczywistości są to moje sugestie.

  1. Replikacja, nawet jeśli powiedziałeś, że nie będziesz jej używać. Jest to najłatwiejsze i najlepsze rozwiązanie, którego możesz użyć do tego. Replikacja jest łatwa w konfiguracji, szybko się replikuje i nie musisz wymyślać koła ponownie. Jeśli po prostu dziwne jest blokowanie, możesz spróbować ustawić to ISOLATION LEVELna READ_COMMITTED_SNAPSHOT. Możesz przeczytać więcej na ten temat tutaj . To zużyje część twojego tempdb, ale twoja tabela jest zawsze do odczytu i zapisu, a replikacja może działać w tle.

Zobacz przykład poniżej:

ALTER DATABASE yourDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE yourDatabase SET READ_COMMITTED_SNAPSHOT ON
  1. CDC (Change Data Capture) może być również rozwiązaniem. Ale w ten sposób musisz samodzielnie zbudować prawie wszystko. I podjąłem doświadczenie, które CDCw niektórych okolicznościach może być delikatne. CDCprzechwyci wszystkie dane z obserwowanej tabeli (musisz ręcznie określić każdą obserwowaną tabelę). Następnie otrzymasz wartość przed, a wartość po INSERT, UPDATElub DELETE. CDCzatrzyma te informacje przez pewien czas (możesz je podać samodzielnie). Podejściem może być użycie CDCw niektórych tabelach, które należy oglądać i ręcznie replikować te zmiany do innej bazy danych. Nawiasem mówiąc, CDCużywa również replikacji SQL Server pod maską. ;-) Możesz przeczytać o tym więcej tutaj .

Ostrzeżenie: CDCnie będzie świadomy DDLzmian. Oznacza to, że jeśli zmienisz tabelę i dodasz nową kolumnę, CDCobejrzy ją, ale zignoruje wszystkie zmiany w nowej kolumnie. W rzeczywistości rejestruje tylko NULLwartość przed i wartość po. Musisz ponownie zainicjować go po DDL-Zmiana obserwowanego stołu.

  1. Opisany powyżej sposób przypomina przechwytywanie obciążenia za pomocą SQL Server Profiler i uruchamianie go ponownie w innej bazie danych dla niektórych testów porównawczych. Cóż, to może zadziałać. Ale fakt, że efektów ubocznych jest zbyt wiele, jest dla mnie trochę za ciężki. Co robisz, jeśli przechwytujesz wywołanie procedury na swoim kliencie. Następnie uruchom to samo polecenie w bazie danych zasad, ponieważ nie jest zsynchronizowane? Procedura może zostać uruchomiona, ale może usunąć / zaktualizować / wstawić wiersze, które nie były obecne w twoim kliencie. Lub w jaki sposób obsługiwać wielu klientów według jednej zasady. Myślę, że to jest zbyt trudne. W najgorszym przypadku prawdopodobnie zniszczysz swoją uczciwość.
  2. Innym pomysłem może być aplikacja lub wyzwalacz. W zależności od liczby tabel, które chcesz zsynchronizować. Możesz zapisać wszystkie zmiany w osobnej tabeli pomostowej i uruchomić zadanie agenta programu SQL Server wszystkie x minuty, aby zsynchronizować te wiersze w tabeli pomostowej z urządzeniem głównym. Ale może to być nieco zbyt trudne, jeśli spróbujesz zsynchronizować (np.) 150 tabel. Miałbyś duże koszty ogólne.

To są moje 2 centy. Mam nadzieję, że masz dobry przegląd i być może znalazłeś jedno rozwiązanie, które będzie dla ciebie odpowiednie.

joński
źródło
9

Spróbuję wymienić tutaj niektóre opcje z zaletami i wadami, gdy je dostrzegam:

  1. Replikacja SQL Server - jest to najlepsze i najbardziej zoptymalizowane natywne narzędzie SQL Server do tego zadania. Ale istnieje kilka problemów: a. dla wszystkich klientów, niezależnie od tego, czy są to bazy danych SQL Express, czy nie, potrzebujesz licencji CAL SQL Server. Można tego uniknąć, stosując licencje na procesor. b. Nie można zsynchronizować klienta SQL CE zgodnie z tutaj . do. SQL Express lub LocalDB nie mogą działać jako wydawca lub dystrybutor , więc masz mniejszą kontrolę nad procesem replikacji na kliencie.
  2. Microsoft Sync Framework - wydaje mi się bardziej odpowiedni dla mniejszych baz danych aplikacji mobilnych. Dodaje do bazy danych sporo tabel i nie jest tak wydajna jak replikacja. Ponieważ jest implementowany poza SQL Server jako komponent, konfiguracja będzie trudniejsza. Nie mam z tym doświadczenia, tylko wypróbowałem go i postanowiłem go nie używać.

  3. Śledzenie zmian w bazie danych . Jest to wbudowana funkcja SQL Server, która wykonuje śledzenie zmian, w tym wstawiania, aktualizacji i usuwania. Wszystko inne, jak wysyłanie i stosowanie zmian, rozwiązywanie konfliktów itp., Będziesz musiał sam kodować.

  4. Kolumny konwersji wierszy (znacznik czasu) Jeśli nie zezwalasz na wszystkie usunięcia (brak synchronizacji usuniętych rekordów) - możesz wdrożyć własne rozwiązanie oparte tylko na informacjach na temat konwersji wierszy. Kolumny konwersji wiersza są również używane przez replikację programu SQL Server, więc i tak trzeba je dodać.
  5. CDC, jak wspomniano w odpowiedzi Ionic - nie mam z tym doświadczenia, ponieważ jest dostępny tylko w wersjach Enterprise lub Developer.

  6. Korzystanie z własnej sztuczki przy rejestrowaniu wykonanych procedur przechowywanych - zależy w dużej mierze od charakteru aplikacji bazy danych. Ale kiedy procedury stają się nieco inne, możesz mieć duży bałagan w danych. A jak poradziłbyś sobie z konfliktami?

Z twojego pytania wynika, że ​​musisz zsynchronizować tylko kilka tabel, a nie całe duże bazy danych. W tym celu należy przeanalizować swoje potrzeby bardziej szczegółowo niż określono w pytaniu, na przykład:

  • Czy usuwanie może się zdarzyć, a co wtedy?
  • Czy mogą się zdarzyć konflikty, jak im zapobiegać i jak je rozwiązywać?
  • Jak poradzę sobie ze zmianami struktury tabeli?
  • ...

Jeśli w końcu okaże się, że usuwanie i konflikty nie są twoim problemem i że twoja struktura niewiele się zmieni, możesz rozważyć napisanie własnej logiki, ale z łatwością może ona wzrosnąć do 1000 wierszy kodu.

Vojtěch Dohnal
źródło
2

Dziękujemy wszystkim za opinie.

Z powodzeniem rozwiązałem proces synchronizacji, przechwytując wykonane procedury przechowywane nie jako kilka, ale jedna po drugiej, co w moim przypadku działało świetnie. Ponieważ rzetelność i wszystko jest dokładnie przemyślane, do tej pory system działał w czasie rzeczywistym.

Emad Farrokhi
źródło
Świetnie, ale możesz wyjaśnić bardziej szczegółowo, co zrobiłeś. Czy po prostu rejestrujesz wywołania procedur przechowywanych, które zostały wykonane i zapisujesz je w tabeli tymczasowej / w skrypcie tymczasowym, a zadanie uruchamia ten skrypt i ustawia pole (takie jak pole bitowe lub pole daty i godziny, w którym wypowiadasz WSZYSTKIE te rekordy, które nie zostały przetworzone, przetwarzają je i aktualizują pole bitowe?) Cieszę się, że rozwiązałeś problem, ale potrzebujesz więcej informacji na temat tego, co zrobiłeś, aby pomóc innym w nauce?
JonH
0

Późna odpowiedź, ale pomocne mogą być odwiedzający wątki

Miałem podobne wyzwanie, próbując dystrybuować dane między różnymi serwerami i rozwiązałem je za pomocą narzędzi firm trzecich ( Diff w przypadku zmian schematu i DataDiff w przypadku synchronizacji zmian danych) i wykonania skryptu PowerShell wymaganego do automatyzacji procesu:

#check for the existence of the Outputs folder
function CheckAndCreateFolder($rootFolder, [switch]$Outputs)
{
$location = $rootFolder

#setting up location 
if($Outputs -eq $true)
{
    $location += "\Outputs"
}

#if the folder doesn't exist it will be created
if(-not (Test-Path $location))
{ mkdir $location -Force:$true -Confirm:$false | Out-Null }

return $location
}

#root folder for the schema sync process
$rootFolder = "SchemaSync"

#schema output summaries location 
$outsLoc = CheckAndCreateFolder $rootFolder -Outputs

#ApexSQL Diff location, date stamp variable is defined, along with tools parameters 
$diffLoc   = "ApexSQLDiff"
$stamp = (Get-Date -Format "MMddyyyy_HHMMss") 
$Params = "/pr:""MyProject.axds""    /out:""$outsLoc\SchemaOutput_$stamp.txt"" /sync /v /f" 
$returnCode = $LASTEXITCODE

#initiate the schema comparison and synchronization process
(Invoke-Expression ("& `"" + $diffLoc +"`" " +$Params))

#write output to file
"$outsLoc\SchemaOutput_$dateStamp.txt"

#schema changes are detected
if($returnCode -eq 0)
{
"`r`n $returnCode - Schema changes were successfully synchronized" >> 

}
else
{
#there are no schema changes
if($returnCode -eq 102)
{
"`r`n $returnCode - There are no schema changes. Job aborted" >> 
}
#an error is encountered
else
{
"`r`n $returnCode - An error is encountered" >> 

#output file is opened when an error is encountered
Invoke-Item "$outsLoc\SchemaOutput_$stamp.txt"
}

}

Ta metoda planuje porównanie dwóch baz danych i synchronizuje znalezione zmiany w czasie rzeczywistym. Oto kilka artykułów zawierających instrukcje krok po kroku:

https://solutioncenter.apexsql.com/automatically-compare-and-synchronize-sql-server-data/ https://solutioncenter.apexsql.com/how-to-automatically-keep-two-sql-server-database- schemas-in-sync /

Monte Chavis
źródło