Синхронізація двох баз даних у SQL Server


16

У мене є дві бази даних SQL Server. Один - клієнт (додаток Windows), а другий - на сервері. Я хочу так часто синхронізувати ці дві бази даних (наприклад, кожні 2 хвилини!).

Я читав про різні способи синхронізації, такі як реплікація, часова марка, таблиці журналів за допомогою тригерів, Microsoft Sync Framework тощо.

Насправді мені не подобається використовувати метод синхронізації, який може бути чорним полем (наприклад, реплікація), оскільки я не хочу, щоб конкретні таблиці SQL Server були заблоковані, коли я їх оновлював і синхронізував із сервером.

  1. який метод, на вашу думку, я повинен використовувати в таких умовах? Пам’ятайте, що кожні кілька хвилин я повинен надсилати кілька змін таблиці від клієнта на сервер і також отримувати дві зміни таблиці з сервера.

  2. Я знайшов метод, який дивний, але новий. Чи можливо, що я реєструю всі виконані (для конкретних бажаних) збережених процедур у клієнті та надсилаю їх зі своїми параметрами у .sqlфайл на сервер і виконую їх там? Те саме відбудеться на сервері та відправляється клієнту. Ви вважаєте, що це простий, але корисний метод чи ні?

  3. будь ласка, підкажіть будь-який корисний підхід, якщо можете. Дуже дякую.

EDIT: Пам'ятайте, що це синхронізація в режимі реального часу, і це робить її особливою. Це означає, що коли користувач-клієнт використовує таблицю, процес синхронізації з сервером повинен відбуватися кожні кілька хвилин, тому жодна з таблиць не повинна бути заблокована.


1
Пам’ятайте, що ці «чорні скриньки» відносно добре зафіксовані щодо того, як вони працюють, як підтримувати та контролювати їх, і що ви можете зробити, щоб виправити їх у загальних (і не дуже поширених) сценаріях відмов. Я б розглядав можливість прокрутки власного методу синхронізації та потребував пошуку та виправлення помилок, пов’язаних із крайовими справами, до яких «чорні скриньки» вирішувались давно, лише тоді, якщо у мене були б особливі потреби в застосуванні (часткова синхронізація чи потреба у користувальницькій, інтерактивне вирішення конфліктів тощо).
Девід Спіллетт

@DavidSpillett: Ви успішно використовували реплікацію в проекті синхронізації в реальному часі? Моє головне питання - це синхронізація в режимі реального часу та "блокування та блокування".
Емад Фаррохі

Відповіді:


14

Добре, що я не можу цього зрозуміти, але намагаюся відповісти.

Ви сказали, що вам потрібно високоефективне рішення, яке працює часто (мінімум усі 2 хвилини) і вам потрібен хороший підхід, який повинен бути швидким, не замикаючись. Але ви не хочете, щоб система blackbox.

Замість системи blackbox, яка використовується на мільйонах установок з хорошими результатами, ви намагаєтесь знову винайти колесо і створити власне рішення? Гм, це звучить трохи дивно.

Насправді це мої пропозиції.

  1. Реплікація, навіть якщо ви сказали, що не будете її використовувати. Це досить просте і найкраще рішення, яке ви можете використовувати для цього. Реплікацію легко встановити, швидко копіювати, і вам не доведеться винаходити колесо знову. Якщо ви просто дивно про блокування, ви можете спробувати встановити ISOLATION LEVELв READ_COMMITTED_SNAPSHOT. Більше про це можна прочитати тут . Це задіяє частину вашого tempdb, але ваша таблиця завжди читається і записується, і реплікація може працювати у фоновому режимі.

Дивіться приклад нижче:

ALTER DATABASE yourDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE yourDatabase SET READ_COMMITTED_SNAPSHOT ON
  1. CDC (Change Data Capture) також може бути рішенням. Але таким чином потрібно будувати майже все самостійно. І я зробив досвід, який CDCможе стати крихкою справою за деяких обставин. CDCбуде захоплювати всі дані в переглянутій таблиці (потрібно вказати кожну переглянуту таблицю вручну). Після цього ви отримаєте значення раніше та значення після INSERT, UPDATEабо DELETE. CDCбуде зберігати цю інформацію протягом певного часу (ви можете вказати її самостійно). Підхід може бути використаний CDCдля певних таблиць, які потрібно переглянути і вручну повторити ці зміни в іншій базі даних. До речі, CDCпід капотом теж використовується реплікація SQL Server. ;-) Більше про це можна прочитати тут .

Попередження: CDCзміни не будуть відомі DDL. Це означає, що якщо ви зміните таблицю і додасте новий стовпець, вона CDCбуде переглядати таблицю, але ігнорувати всі зміни до нового стовпця. Насправді він записує лише NULLяк значення до та значення після. Потрібно повторно DDLактивізувати його після -Зміни на переглянуту таблицю.

  1. Вище описаний спосіб є чимось схожим на захоплення робочого навантаження за допомогою SQL Server Profiler і запустити його знову в іншій базі даних для деяких орієнтирів. Що ж, це може спрацювати. Але факт занадто багато побічних ефектів для мене трохи важкий. Що ви робите, якщо здійснюєте процедурний дзвінок у свого клієнта. Згодом виконати ту саму команду у вашій базовій базі даних, яка не синхронізована? Процедура може запуститися, але вона може видалити / оновити / вставити рядки, яких не було у вашого клієнта. Або як ви керуєтесь кількома клієнтами за одним принципом. Я думаю, що це занадто хитро. У гіршому випадку ви, ймовірно, руйнуєте свою цілісність.
  2. Іншою ідеєю може бути додаток на основі або використання тригера. Залежно від того, скільки таблиць потрібно синхронізувати. Ви можете записати всі зміни в окрему таблицю інсценізації та запустити роботу агента SQL Server усі хвилини, щоб синхронізувати ці рядки в таблиці інсценізації з вашим майстром. Але це може бути важким, якщо ви спробуєте синхронізувати (наприклад) 150 таблиць. У вас були б великі накладні витрати.

Ну це мої 2 копійки. Сподіваємось, у вас хороший огляд, і, можливо, ви знайшли одне рішення, яке працює для вас.


9

Я спробую перерахувати тут декілька варіантів із перевагами та недоліками, коли їх сприймаю:

  1. Реплікація SQL Server - це найкращий і найбільш оптимізований нативний інструмент SQL Server для цього завдання. Але є кілька проблем: а. для всіх ваших клієнтів, незалежно від того, є вони базами даних SQL Express чи ні, вам знадобиться ліцензія CAL для SQL Server. Цього можна уникнути, використовуючи ліцензію на процесор. б. Ви не можете синхронізувати клієнт SQL CE, як описано тут . c. SQL Express або LocalDB не можуть виступати видавцем чи розповсюджувачем , тому у вас менше контролю над клієнтом над процесом реплікації.
  2. Microsoft Sync Framework - мені здається, більше підходить для менших баз даних мобільних додатків. Це додає досить багато таблиць у вашу базу даних, і це не так ефективно, як реплікація. Оскільки він реалізований за межами SQL Server як компонент, його буде складніше налаштувати. Я не маю досвіду з цим, лише спробував його і вирішив не використовувати.

  3. Відстеження змін бази даних . Це вбудована функція SQL Server, яка дозволяє змінювати відстеження, включаючи вставки, оновлення та видалення. Все інше, як надсилання та застосування змін, вирішення конфліктів тощо, вам доведеться кодувати себе.

  4. Стовпці Rowversion (мітки часу) Якщо ви забороните всі видалення (не синхронізація видалених записів) - ви можете реалізувати власне рішення, засноване лише на інформації про версію. Стовпці Rowversion використовуються також у реплікації SQL Server, тому вам доведеться додавати їх як завгодно.
  5. CDC, як згадується у відповіді Ionic - я не маю цього досвіду, оскільки він доступний лише у виданнях Enterprise або Developer.

  6. Використання власного трюку при реєстрації виконаних збережених процедур - дуже залежить від характеру вашої програми бази даних. Але коли процедури трохи відрізняються, там ви можете отримати великий безлад у даних. І як би ви вирішили конфлікти?

З вашого запитання виходить, що вам потрібно синхронізувати лише кілька таблиць, а не цілі великі бази даних. Для цього слід проаналізувати свої потреби більш детально, ніж ви вказали у запитанні, як-от:

  • Чи можуть відбуватися видалення, і що відбувається потім?
  • Чи можуть статися конфлікти, як їх запобігти і як їх вирішити?
  • Як я буду мати справу зі змінами структури таблиці?
  • ...

Якщо ви зрештою з’ясуєте, що видалення та конфлікти - це не ваша проблема, і ваша структура не зміниться сильно, ви можете розглянути можливість написання власної логіки, але вона може легко вирости до 1000 рядків коду.


2

Дякую всім за відгуки.

Я успішно вирішив процес синхронізації, захопивши виконані збережені процедури не як купу, а одну за одною, що чудово працювало в моєму випадку. Оскільки цілісність і все ретельно продумано, система працює до теперішнього часу.


Чудово, проте ви можете, будь ласка, пояснити детальніше, що ви робили. Ви просто записуєте виклики збережених процедур, які були виконані, і зберігаєте їх у якійсь темп-таблиці / скрипті, і у вас є завдання, запустіть цей сценарій і встановіть поле (наприклад, бітове поле або поле дати, де ви говорите для ВСІХ цих записи, які не були оброблені, обробляють їх та оновлюють бітове поле?) Я щасливий, що ви вирішили свою проблему, але вам потрібно детальніше зрозуміти, що ви зробили, щоб допомогти іншим навчатися?
JonH

0

Пізня відповідь, але це може бути корисно для відвідувачів

У мене було подібне завдання, намагаючись розподілити дані на різних серверах і вирішити їх за допомогою сторонніх інструментів ( Diff для змін схеми та DataDiff для синхронізації змін даних) та дотримуючись сценарію PowerShell, необхідного для автоматизації процесу:

#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"
}

}

Цей метод планує порівняння між двома базами даних та синхронізує знайдені зміни в режимі реального часу. Ось кілька статей, що пропонують покрокові інструкції:

https://solutioncenter.apexsql.com/automatically-compare-and-synchronize-sql-server-data/ https://solutioncenter.apexsql.com/how-to-automatically-keep-two-sql-server-database- схеми синхронізації /

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.