Синхронизация структуры базы данных между приложениями. Сравнение программ для синхронизации сетевых баз данных. Бесплатная программа для синхронизации
Приложения, используемые торговыми представителями или другими работниками на местах – курьеры службы доставки, выездные медсёстры, сотрудники клининговых компаний и т.д., предназначены для сбора информации на местах с последующей отправкой её в центр обработки данных. Кроме того, периодически необходима обратная связь, т.е. отправка данных обратно от центра обработки к конкретным исполнителям на местах.
Например, каждый раз, когда медсестра осуществляет визит к пациенту, она делает отметку о визите на мобильном устройстве. По итогам рабочего дня, вся информация отправляется в централизованную базу данных больницы. После этого, они могут синхронизировать свои мобильные устройства с центром обработки данных, чтобы получить актуальную информацию о своих пациентах или узнать список новых посещений, который они должны осуществить на следующий день.
В любом подобном сценарии использования основная потребность – это постоянный обмен данными между мобильными устройствами на местах и общим хранилищем данных.
Как можно решить подобные задачи
1. Репликация SQL Server. С помощью репликации вы можете осуществлять синхронизацию удалённых баз данных между собой путём копирования данных. Но у неё (репликации SQL Server) есть ряд ограничений:
- Только более дорогие редакции SQL Server Standard и Enterprise могут выступать в роли издателя (Publisher), поэтому если вы используете бесплатную редакцию SQL Express, то вам придётся обновиться.
- Конфигурация из издателя (Publisher) SQL Server 2005 и подписчика (Subscriber) SQL Server 2008 не поддерживает web-репликацию.
- Версия распространителя (Distributor) должна быть строго равна или выше версии издателя (Publisher).
- В репликации транзакций (Transactional Replication) версия подписчика (Subscriber) не должна отличаться от издателя (Publisher) больше, чем на две версии SQL Server, т.е. издатель SQL Server 2000 не может работать с подписчиком SQL Server 2012.
- В репликации слиянием (Merge Replication) версия подписчика (Subscriber) должна быть меньше или равна версии издателя (Publisher), т.е. подписчик SQL Server 2012 не сможет работать с издателем SQL Server 2008.
2. Sync Framework
– API, которое позволяет создавать приложения для синхронизации данных между разными базами данных. Эта платформа более гибкая для решения подобных задач, но требует дополнительной разработки, что повышает стоимость и сроки реализации.
3. ApexSQL Data Diff – инструмент SQL Server для поиска различий в данных и синхронизации их между собой. Этот инструмент позволяет находить различия не только между базами данных, но и анализировать резервные копии БД, как обычные, так и сжатые. В результате анализа можно получить подробный отчёт о найденных расхождениях и файл синхронизации, который можно выполнить.
Как это сделать
Представьте себе, что у вас есть единое хранилище данных больницы (Central) и базы данных посещения (Visits) на мобильном устройстве медсестры. В больнице создаются записи в таблице посещения (Visits) и каждое утро медсёстры синхронизируют свои устройства, чтобы узнать свой маршрут на предстоящий день. В течении дня медсёстры на мобильных устройствах желают пометки о посещениях в таблице VisitReports.
Для обратной синхронизации всех изменений, которые совершили медсёстры в течении дня необходимо выполнить похожие действия:
Теперь рассмотрим, как автоматизировать процесс синхронизации, при наличии проектов синхронизации.
Для вечерней синхронизации повторите шаги с 3 по 9, чтобы создать ещё одно задание.
С помощью приложения ApexSQL Data Diff вы можете легко настроить синхронизацию ваших удалённых БД SQL Server с центральным хранилищем. При этом вы не привязаны к какой-то конкретной версии или редакции SQL Server, от вас не потребуется дополнительного времени на разработку, при этом вы осуществляете полный контроль над всеми вашими данными до единой записи.
Каждый, кто когда-либо разрабатывал приложения, использующие базу данных, наверняка сталкивался с проблемой обновления структуры БД при разворачивании и обновлении приложения.
Чаще всего используется простой подход - создание набора SQL-скриптов для модификации структуры БД от версии к версии. Конечно, есть такой мощный инструмент, как Red gate , но он во-первых небесплатный, во-вторых не решает проблему полной автоматизации обновления.
Технология migrations, впервые появившаяся в ОРМ Hibernate и реализованная в Linq, очень хороша и удобна, но подразумевает стратегию разработки структуры БД code first, что весьма трудоемко для уже существующих проектов, а использование в БД триггеров, хранимых процедур и функций делает задачу перехода на code first практически невыполнимой.
В данной статье предлагается альтернативный подход к решению этой задачи, использующий хранение эталонной структуры БД в XML-файле и автоматическую генерацию SQL-скрипта на основе сравнения эталонной и существующей структуры. Итак, начнем...
Генерация XML-файла со структурой БД
Для экспериментов будем использовать БД DbSyncSample. Скрипт для создания БД приведен ниже.
USE GO /****** Object: Table . Script Date: 06/01/2017 10:37:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE .( IDENTITY(1,1) NOT NULL, (50) NULL, NULL, (18, 2) NOT NULL, CONSTRAINT PRIMARY KEY CLUSTERED ( ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ) ON GO CREATE NONCLUSTERED INDEX ON . ( ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON GO /****** Object: Table . Script Date: 06/01/2017 10:37:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE .( IDENTITY(1,1) NOT NULL, (150) NULL, NULL, (18, 2) NOT NULL, CONSTRAINT PRIMARY KEY CLUSTERED ( ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ) ON GO /****** Object: Trigger Script Date: 06/01/2017 10:37:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TRIGGER . ON . AFTER INSERT,UPDATE AS BEGIN UPDATE Orders SET TotalCost = s.Total FROM (SELECT i.OrderId OId, SUM(d.Cost) Total FROM Details d JOIN inserted i ON d.OrderId=i.OrderId GROUP BY i.OrderId) s WHERE Id=s.OId END GO /****** Object: Trigger Script Date: 06/01/2017 10:37:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TRIGGER . ON . AFTER DELETE AS BEGIN UPDATE Orders SET TotalCost = s.Total FROM (SELECT i.OrderId OId, SUM(d.Cost) Total FROM Details d JOIN deleted i ON d.OrderId=i.OrderId GROUP BY i.OrderId) s WHERE Id=s.OId END GO /****** Object: Default Script Date: 06/01/2017 10:37:43 ******/ ALTER TABLE . ADD CONSTRAINT DEFAULT ((0)) FOR GO /****** Object: Default Script Date: 06/01/2017 10:37:43 ******/ ALTER TABLE . ADD CONSTRAINT DEFAULT ((0)) FOR GO /****** Object: ForeignKey Script Date: 06/01/2017 10:37:43 ******/ ALTER TABLE . WITH CHECK ADD CONSTRAINT FOREIGN KEY() REFERENCES . () GO ALTER TABLE . CHECK CONSTRAINT GO
Для экспериментов создаем консольное приложение. Подключаем к нему nuget-пакет Shed.DbSync .
Структуру БД в виде XML получаем следующим образом:
class Program { private const string OrigConnString = "data source=.;initial catalog=FiocoKb;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"; static void Main(string args) { // получаем XML со структурой БД var db = new Shed.DbSync.DataBase(OrigConnString); var xml = db.GetXml(); File.WriteAllText("DbStructure.xml", xml); } }
После запуска программы в файле DbStructure.xml видим следующее:
Разворачивание/обновление структуры БД при помощи полученного XML.
Теперь научимся использовать полученный XML. Создаем еще одну пустую БД DbSyncSampleCopy, в код нашей консольной программы добавляем следующее:
class Program { private const string OrigConnString = "data source=.;initial catalog=DbSyncSample;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"; private const string TargetConnString = "data source=.;initial catalog=DbSyncSampleCopy;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"; static void Main(string args) { // получаем XML со структурой эталонной БД var dborig = new Shed.DbSync.DataBase(OrigConnString); var xml = dborig.GetXml(); File.WriteAllText("DbStructure.xml", xml); // если нужно предварительно очистить структуру целевой БД, используем // Shed.DbSync.DataBase.ClearDb(TargetConnString); // обновляем структуру целевой БД var dbcopy = Shed.DbSync.DataBase.CreateFromXml(xml); dbcopy.UpdateDb(TargetConnString); // на самом деле можно обойтись одной строкой: // dborig.UpdateDb(TargetConnString); // dbcopy создаем только для демонстрации создания объекта базы из XML } }
После запуска программы можно убедиться, что в DbSyncSampleCopy появилась структура таблиц, идентичная эталонной БД. Эксперименты с изменением эталонной структуры и обновлением целевой оставляю читателю.
В сценариях тестирования может понадобиться создание тестовой БД каждый раз с нуля. В этом случае будет полезно использовать функцию Shed.DbSync.DataBase.ClearDb(string connString)
Автоматическое слежение за структурой БД.
Слежение за структурой оформим в виде отдельной функции, которую следует вызывать при старте/рестарте приложения либо в другом месте по желанию разработчика.
static void SyncDb() { // автоматическое слежение за структурой БД Shed.DbSync.DataBase.Syncronize(OrigConnString, @"Struct\DbStructure.xml", // путь к файлу структуры @"Struct\Logs", // путь к папке логов синхронизации @"Struct\update_script.sql" // (необяз.) в случае определения этого параметра // в него будет записан скрипт, сгенерированный // для обновления БД); }
Слежение производится при помощи параметра (тега) Version в XML. Сценарий использования процедуры такой:
- Назначить версию БД. В Microsoft SqlServer Management Studio на узле нужной базы данных правой кнопкой выбрать Properties.
- Далее Extended Properties и в таблице свойств добавить свойство Version со значением 1. При каждой последующей модификации структуры это свойство следует наращивать на 1.
- При запуске приложения, если XML-файла нет или его версия меньше, чем у БД, он создается.
- Если версия XML-файла больше, чем у БД, генерируется скрипт на обновление БД и исполняется.
- Если в процессе исполнения скрипта возникли ошибки, все изменения откатываются.
- Результаты синхронизации пишутся в log-файл, создаваемый в папке, указанной параметром logDitPath.
- Если указан параметр SqlScriptPath, создается файл со скриптом из п.4.
Эксперименты оставляю читателям. Успехов вам!
Теги:
- ms sql
- синхронизация баз данных
- database
- syncronize
- dbsync
- sql
- shed
- shed.dbsync
При разработке современных веб-приложений сложно недооценить пользу от использования систем контроля версий. Применительно к файлам разрабатываемого продукта, мы способны отследить любые этапы производства в любой момент, начиная с первой ревизии. Инструменты, помогающие нам в этом, на сегодняшний день популяризированы, считаются хорошим тоном при разработке, а во многих случаях успешное производство без их применения невозможно в принципе. А какие возможности мы имеем, когда возникает необходимость проследить изменения не в файлах, а в базах данных проекта? Под катом я поделюсь информацией о существующих средствах, с которыми мне пришлось ознакомиться.
1. PHP SQLDIFF, a.k.a. SQLDiff
PHP-скрипт, позволяющий увидеть полные различия (как в структуре, так и в данных) между любыми таблицами двух БД. В инструменте отсутствуют какие-либо средства по автоматической синхронизации структуры или данных – предоставляется лишь визуальная информация. Еще из существенных недостатков – возможность подключения только к БД, к которым возможен доступ напрямую (не через ssh-тоннель). Медленная скорость работы на больших объемах данных (работа через pear-модуль, который не блещет ни новизной, ни скоростью). Считаю данный скрипт весьма полезным для разработчика в случаях, когда необходимо понимание и визуальное представление различий между разными таблицами - имеет удобный интерфейс, быстрая настройка. Охарактеризую скорее как полезную карманную утилиту для быстрого получения понимания о рассинхронизации таблиц, которые в теории должны быть идентичны, нежели как серьезный инструмент, который можно применить для автоматизации процессов синхронизации.
2. LIQUIBASE
Удобный многофункциональный и простой в использовании мигратор структуры БД на java. Вижу для себя в этом плюс, если использовать в связке с Jenkins.
Пример (host1 - сервер, с которого необходимо копировать структуру БД; host2 - сервер, на который необходимо перенести структуру с host1):
Java -jar liquibase.jar --driver=com.mysql.jdbc.Driver --classpath=mysql-connector-java-5.1.xx-bin.jar --logFile=db.ExampleChangelog.xml --url="jdbc:mysql://host2" --defaultSchemaName=db_name --username=username --password="password" --referenceUrl=jdbc:mysql://host1 --referenceUsername=username --referencePassword="password" diffChangeLog > ChangeSet.xml
Формирует changeset в формате xml, дальнейшая миграция которого приводит структуру бд на host2 в состояние, идентичное host1.
Запуск миграции:
Java -jar liquibase.jar --driver=com.mysql.jdbc.Driver --classpath=/path/to/classes --changeLogFile=ChangeSet.xml --url="jdbc:mysql://host2" --username=user --password="password" migrate
После миграции есть смысл проверить еще раз, что changeset пустой.
Происходит не только синхронизация таблиц и полей, но также индексов, ключей. Не уверен по поводу хранимых процедур – это я не проверил.
Changeset также можно формировать и в других форматах - в sql, в json (не только в xml). Формирование changeset"а в sql будет полезным в тех случаях, когда для миграции используются средства другой утилиты.
3. schemasync
Инструмент для синхронизации структуры БД. Для работы необходим python и соответствующий интерфейс для mysql.
Из существенных различий с liquibase:
- schemasync создает не только ченжсет, но и файл, позволяющий откатить изменения (самое важное и самое ценное преимущество, хотя, на мой взгляд, не избавляет от необходимости делать backup перед синхронизацией)
- liquibase позволяет не только получить ченжсет, но и сразу же запустить миграцию средствами самой утилиты. Может быть, не киллер-фича, но все равно удобно и полезно
schemasync работает только с sql – никаких промежуточных xml и аналогов – вижу для себя в этом как преимущества, так и недостатки.
Очень лаконичный синтаксис, минимум настроек. Позволяет не синхронизировать комментарии и автоинкремент (настраивается) - безусловный плюс.
Пример использования:
Schemasync mysql://user:pass@dev-host:3306/dev_db mysql://user:pass@prod-host:3306/production_db