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

16

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

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

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

  1. Какой метод вы думаете, что я должен использовать в таких обстоятельствах? Помните, что каждые несколько минут я должен отправлять несколько изменений таблицы с клиента на сервер и получать также два изменения таблицы с сервера.

  2. Я нашел метод, который странный, но новый. Возможно ли, чтобы я регистрировал все выполненные (для конкретных предпочтительных) хранимых процедур в клиенте, отправлял их с параметрами в .sqlфайле на сервер и выполнял там? То же самое произойдет на сервере и отправлено клиенту. Как вы думаете, это простой, но полезный метод или нет?

  3. Пожалуйста, предложите мне любой полезный подход, если можете. Огромное спасибо.

РЕДАКТИРОВАТЬ: Помните, что это синхронизация в реальном времени, и это делает его особенным. Это означает, что когда пользователь клиента использует таблицу, процесс синхронизации с сервером должен происходить каждые несколько минут, поэтому ни одна из таблиц не должна быть заблокирована.

Эмад Фаррохи
источник
1
Помните, что эти «черные ящики» относительно хорошо документированы относительно того, как они работают, как их поддерживать и контролировать, и что вы можете сделать, чтобы исправить их в общих (и не очень) сценариях сбоев. Я хотел бы рассмотреть возможность использования моего собственного метода синхронизации и необходимости находить и исправлять ошибки, связанные с крайними случаями, к которым «черные ящики» обращались давным-давно, если и только если у меня были очень специфические потребности приложения (частичная синхронизация или потребность в интерактивное разрешение конфликтов и т. д.).
Дэвид Спиллетт
@DavidSpillett: Вы успешно использовали репликацию в проекте синхронизации в реальном времени? Моя главная задача - синхронизация в реальном времени и «блокировка и блокировка».
Эмад Фаррохи

Ответы:

14

Ну, я могу не получить это, но я пытаюсь ответить на это.

Вы сказали, что вам нужно высокопроизводительное решение, которое запускается часто (минимум все 2 минуты), и вам нужен хороший подход, который должен быть быстрым без блокировки. Но вы не хотите систему черного ящика.

Вместо системы черного ящика, которая используется на миллионах установок с хорошими результатами, вы пытаетесь снова изобрести колесо и создать собственное решение? Хм, звучит немного странно.

На самом деле это мои предложения.

  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 Replication под капотом. ;-) Подробнее об этом можно прочитать здесь .

Предупреждение: CDCне будут знать о- DDLизменениях. Это означает, что если вы измените таблицу и добавите новый столбец, CDCбудете наблюдать за таблицей, но игнорировать все изменения в новом столбце. На самом деле он записывает только NULLзначение до и значение после. Вам нужно DDLповторно инициализировать его после - Изменения в отслеживаемой таблице.

  1. Способ, описанный выше, напоминает захват рабочей нагрузки с использованием SQL Server Profiler и ее повторное выполнение в другой базе данных для некоторых тестов. Ну, это может сработать. Но тот факт, что есть слишком много побочных эффектов, является слишком тяжелым для меня. Что вы делаете, если вы фиксируете вызов процедуры на своем клиенте. После того, как вы выполнили ту же команду в вашей основной базе данных, поскольку она не синхронизирована? Процедура может выполняться, но она может удалять / обновлять / вставлять строки, которых не было в вашем клиенте. Или как вы работаете с несколькими клиентами по одному принципу. Я думаю, что это слишком сложно. В худшем случае вы, вероятно, разрушаете свою целостность.
  2. Другой идеей может быть приложение или использование триггера. В зависимости от того, сколько таблиц вы хотите синхронизировать. Вы можете записать все изменения в отдельную промежуточную таблицу и запустить задание агента SQL Server все x минут, чтобы синхронизировать эти строки в промежуточной таблице с вашим мастером. Но это может быть немного тяжело, если вы попытаетесь синхронизировать (например) 150 таблиц. У тебя были бы большие накладные расходы.

Ну, это мои 2 цента. Надеюсь, у вас есть хороший обзор, и, возможно, вы нашли одно решение, которое работает для вас.

ионный
источник
9

Я постараюсь перечислить некоторые варианты здесь с преимуществами и недостатками, как я их понимаю:

  1. Репликация SQL Server - это лучший и наиболее оптимизированный инструмент SQL Server для этой задачи. Но есть несколько проблем: а. для всех ваших клиентов, независимо от того, являются они базами данных SQL Express или нет, вам понадобится лицензия SQL Server CAL. Этого можно избежать, используя лицензирование на процессор. б. Вы не можете синхронизировать клиент SQL CE, как здесь . с. 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

Спасибо всем за ваш отзыв.

Я успешно решил процесс синхронизации, записывая выполненные хранимые процедуры не как кучу, а одну за другой, что прекрасно работало в моем случае. Поскольку целостность и все тщательно продуманы, система работала в режиме реального времени до сих пор.

Эмад Фаррохи
источник
Замечательно, но не могли бы вы объяснить подробнее, что вы сделали? Вы просто регистрируете вызовы хранимых процедур, которые были выполнены, и сохраняете их в какой-то временной таблице / скрипте, и у вас есть задание запустить этот скрипт и установить поле (такое как битовое поле или поле даты / времени, где вы говорите для ВСЕХ эти записи, которые не были обработаны, обрабатывают их и обновляют битовое поле?) Я рад, что вы решили свою проблему, но вам нужно дать больше информации о том, что вы сделали, чтобы помочь другим учиться?
Джон
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/automatics-compare-and-synchronize-sql-server-data/ https://solutioncenter.apexsql.com/how-to-automatics-keep-two-sql-server-database- схемы-в-SYNC /

Монте Чавис
источник