Как избежать потери времени при развертывании и поможет ли в этом репликация?
Вы устали от простоев во время развертывания изменений в схеме вашей базы данных.
Как было бы здорово иметь два разных SQL сервера. Тогда Вы смогли бы:
- Направлять клиентский трафик на Сервер А;
- Применять скрипты развертывания на сервере В (который не принимает клиентский трафик).
- Направлять клиентский трафик на недавно развернутый Сервер В.
- И применять скрипты к серверу А (который не принимает клиентский трафик)
Вуаля! Ваши серверы обновлены и синхронизированы, не так ли? Но в случае с SQL сервером такой подход не работает.
Иллюстрирование проблем с помощью простого изменения схемы.
В качестве примера будет использовать таблицу Posts в базе данных Overflow:
Таблица Posts содержит вопросы и ответы. В темные времена столбец Tags содержал до 5 тегов для описания вопроса. В новом дизайне у нас есть возможность разбить столбец Tags по отдельным дочерним таблицам, по одному на строку.
Если бы у нас был только один SQL Server, наше развертывание скрипта выглядело следующим образом:
- Создайте новой таблицу PostsTags: CREATE TABLE dbo.PostsTags (PostId INT, Tag NVARCHAR(40));
- Закройте приложение
- Заполните таблицу (это потребует довольно много работы).
- Измените хранимые процедуры строки insert/update в dbo.Posts, так, чтобы теперь они заполняли новую таблицу dbo.PostsTags
- Запустите приложение снова.
Зачем же закрывать приложение? Потому что люди могут обновлять и вставлять строки в Posts, пока выполняются шаги 3 и 4. Если не остановить приложение, придется выполнять дополнительные шаги кодирования для обнаружения строк dbo.posts, которые были изменены во время выполнения шагов 3 и 4, и делать соответствующие изменения в dbo.PostsTags.
Есть несколько разных способов обойти эту проблему, если у Вас только один SQL сервер:
- Разверните таблицу dbo.PostsTags заблаговременно и измените код, чтобы столбец dbo.Posts.Tags и таблица dbo.PostsTags синхронизировались с новыми inserts/updates, или
- Напишите триггеры для синхронизации столбца и таблицы. или
- Напишите другой процесс (например, SSIS, ADF или ваше собственное приложение) для синхронизации.
Но ни один из вариантов не встроен в SQL Server. Это все дополнительная работа по разработке, которая традиционно не считается частью администрирования.
Решит ли эту проблему репликация?
Логика такова: если бы у нас было два SQL- сервера, мы могли бы произвести все изменения на сервере, пока нет пользовательского трафика:
- Создайте новой таблицу PostsTags: CREATE TABLE dbo.PostsTags (PostId INT, Tag NVARCHAR(40));
- Заполните таблицу (это потребует довольно много работы).
- Измените хранимые процедуры строки insert/update в dbo.Posts, так, чтобы теперь они заполняли новую таблицу dbo.PostsTags
Пока происходят эти изменения какой-то другой SQL сервер обрабатывает весь трафик - таким образом у нас нет никаких проблем с согласованностью, так?
Неверно: этот другой SQL сервер все еще получает inserts & updates в таблицу Posts. Репликация только синхронизирует таблицу Posts: она не переносит изменения между таблицей Posts и PostsTags.
Репликация может использоваться для переноса изменений между различными схемами баз данных, но это зависит от вас. Это не так просто. Вам необходимо написать собственные хранимые процедуры репликации.
Но если Вы все-таки хотите это сделать... репликация Вам не нужна. Как говорилось выше, есть различные способы обойти проблему при наличии только одного SQL-сервера. Они гораздо проще, чем репликация.
Репликация усложняет высокую доступность.
Это звучит странно для тех, кто вырос на других платформах баз данных, где репликация - способ высокой доступности и аварийного восстановления.
Однако, высокая доступность SQL сервера и механизмы аварийного восстановления используют журнал транзакций. У Серверов А и В будут совершенно разные журналы транзакций - они получают различные изменения в разное время.
Из-за различных журналов транзакций, Вам необходимо защищать каждый по отдельности. Если вы используете группы доступности Always On для защиты HA/DR, это означает, что у Вас будет две отдельные группы доступности, каждая в своем наборе серверов (Вы не сможете использовать одни и те же серверы, если хотите использовать только одно имя базы данных: название базы данных должно быть уникальным для каждого сервера).
Таким образом, у Вас окажется запутанный набор реплик для сервера А и В. Вы удвоите количество серверов, корректировок и работы по аварийному восстановлению.
Вы можете сделать все это и были случаи, когда получалось сократить окна отключений по нескольким причинам:
- Скрипты развертывания были очень трудоемкими: либо переписывались целые таблицы, либо изменялся порядок столбцов.
- Хранилище оставляло желать лучшего.
- Никто не беспокоился о высокой доступности и аварийном восстановлении для систем репликации - ежедневно делались снапшоты серверов (при этом всегда нужно быть готовыми к потере данных).
- Массовый набор персонала для написания хранимых процедур репликации - команды из 5-6 человек, которые занимались написанием хранимых процедур для развертываний (потому что это были зрелые приложения с сотнями таблиц, каждая из которых требовала собственных процедур при изменении схемы).
Вы можете делать все то же самое. Честно говоря, не стоит усложнять себе работу - используйте вместо этого односерверные методы или стандартизируйте только аддитивные изменения, а не деструктивные.