Версионирование базы данных - Работа с ветками

Posted by PDSW on Saturday, November 25, 2017
Last Modified on Thursday, February 14, 2019

TOC

Данный текст явлется переводом. Оригинал по ссылке

Предыдущие публикации:

  1. Три правила для работы с базой данных
  2. Построение базиса
  3. Скрипты изменения
  4. Работа вьюшками, хранимыми процедурами и пр.

Если вы не знакомы с ветвлением и слиянием веток, предлагаю вам отличную HOWTO Control Source Eric Sink’s. Я предпочитаю модель бранчевания “релизная ветка” (примечание переводчика: подходы к ветвлению указанные по ссылкам немного устарели. По-моему мнению стоит уделить внимание более современных подходам git-flow, github-flow и gitlab-flow, но понимание сути возможных проблем при миграции изменений думаю может быть полезно).

При подходе “Релизная ветка” вся новая работа происходит в trunk ветке репозитория. Как только продукт приближается к релизу, изменения схемы становятся более редкими и фризятся новые правки. В этот момент, команда создает ветку для релиза. Разработка нового функционала продолжается в транке с изменениями в схеме и всего остального кода. В ветку отправляются только фиксы ошибок. После релиза команда объединяет исправления с ветки в trunk.

Как работать со скриптами при таком подходе?

Это достаточно сложный вопрос.

Изменения схемы в ветке требуют постоянного внимания. Техника только вперед (forward-only, run-once), которую я использую при работе с ветками имеет ряд проблем. Над ними определённо предстоит подумать и вам при разработке вашего процесса миграции баз данных.

К примеру я знаю, что в моем процессе изменения схемы в ветке будут редкими. Если вы используете более агрессивную стратегию ветвления (как feature-branch), такой подход очевидно хорошо работать не будет. В отличии от других стратегий - типо Руби Миграций, которые могут легко продвигаться вперед или назад по изменениями (если вы только не делаете необратимых изменений). Как и в большинстве случаев в нашей отрасли, приходится искать компромисы.

Сценарий работы

Скажем, команда подготовила базу данных на версии 01.00.0000, и написал а 45 сценариев изменения в процессе разработки фич (01.00.0001 до 01.00.0045). Разработка нового функционала сделана, и продукт уже близок к релизу 1.0, поэтому создаём ветку 1.0 (примечание: версия продукта и версия базы данных не обязательно должны совпадать).

В точке ветвления, я создаю новый базис для базы данных. В этом случае, версия базиса 01.01.0000 или 02.00.0000 подходят прекрасно - я просто хочу, увеличить цифру старшего или младшего номера версии. Скажем, мы используем 02.00.0000 в целях продолжения обсуждения. Этот новый базис переходит в trunc. При новой установке базы данных (от транка) нужно просто запустить этот новый скрипт, так как он должен произвести ту же базу данных, что и исходный базис и в дополнение 45 скриптов изменения. Я также проверяю что папка с изменения схемы 02.00.0000 пуста, таким образом существующий базис базы данных забрал в себя этот код.

Теперь представьте, что команда работает дальше и создаёт 2 сценария изменения схемы в транке. Эти изменения 02.00.0001 и 02.00.0002. В этот момент ошибка обнаруживается на продакшене, и для её исправления требуется измененить схему. Тьфу!

Возвращаемся в ветку, команда создает изменения схемы 01.00.0046 и исправляет ошибку в сочетании с комбинацией кода и изменениями скрипта. Это хорошо для системы продакшена потому что он получают только стабильную версию билда, так как эти базы данных никогда не видели скриптов изменения v2.0. Теперь мы можем просто обновить эту системы новой версией 1.0 сборки. Ветка сборки включает в себя и применит 46-й скрипт изменения. Теперь все хорошо, по крайней мере, в мире 1,0.

Но что с транком?

Что-бы добавить это исправление в trunc, есть два варианта решения. Ну, на самом деле существует бесконечное количество вариантов в зависимости от того, как применять ваши обновления, но здесь рассмотри только два варианта:

  1. Объеденить скрипт изменения схемы в trunc из 01.00.0046, и исправить скрипты базиса 2.0, чтобы включить эти изменения.
  2. Написать новый скрипт изменения схемы, 02.00.0003, который имеет такие же изменения, как и изменение 46 в релизной ветке.

С опции №1 вам стоит быть предельно осторожными, потому что любая база данных, которая обновится до версии v2.0 не будет принимать скрипты изменения 46 - й из ветки (если вы не пишете свои инструменты по- другому, чем я). Вы должны будете заставить людей запускать этот скрипт вручную, или вам самим придйтся пройтись и уничтожить все существующие базы данных v2.0 (которые на данный момент должны быть только на машинах разработчиков и машинах для тестирования). Это не самый лучший вариант, но если вы не зашли глубоко в 2.0 иногда этот подход можно назвать приемлимым.

Вариант №2 немного дружелюбнее. Базы данных v1.0 подберут исправление от 01.00.0046. Базы данных v2.0 подберут исправление от 02.00.0003. Вы должны быть осторожны при написании скрипта изменения 02.00.0003, так что-бы он не по-пытаться повторно применить изменения, если сценарий 01.00.0046 всё-таки был запущен ранее.

Другими словами, на базах данных, установленныех из скриптов базиса v2.0 необходимо применить скрипт 02.00.0003, но на базах данных продакшена , которые разрабатывались с версии 1.0 будут использовать скрипт 01.00.0046, и так как вы не хотите, чтобы 02.00.0003 создала ошибку путем добавления изменений, которые уже есть, в тот момент когда база данных будет обновлена ​​до версии 2.0.

Уфф, я надеюсь, что вы все это смогли понять. Ветки и изменения схемы всегда заставляют меня нервничать, но, к счастью, они встречаются редко. Даже тогда, когда они происходят, сценарии изменения обычно включают простые изменения и не похожи на большие изменений, которые вы видите в скриптах, написанных в процессе разработки нового функционала.

Вопросы

В коментариях к предыдущему посту, был задан вопрос:

При добавлении столбца в таблицу, действительно должен быть скрипт для существующих баз данных который бы переносил и обновлял данные, но в то же время в скриптах базиса “создать всю базу данных”, теми что используются для развертывания новой базы данных не требует всю историю сценариев обновления, нужно тоже где-то храниить эти скрипты. Такая кумулятивная синхронизация является сложной для выполнения. Лично мне очень удобно писать скрипт изменения, чтобы переименовать существующий столбец, изменить его тип от VARCHAR к Int также и поддерживать все существующие данные. Не все в команде это могут. Большинство инструментов автоматического создания сценариев не получит применения для таких сложные задач изменения. Делегируя одному человеку в команде типо “разработчик БД” не совсем правильно, в силу bus-фактора.

№1: Обычно, я создаю базис между релизами. Это означает, что новых при установке новой системы придется запустить кучу скриптов обновления, но так как это установка то и весь процесс связанный с запуском скриптов будет автоматизирован, а значит - количество скриптов не имеет большого значения. Преимущество в том, что мне не нужно синхронизировать скрипты базиса, т.е. уменьшается размер задач которые необходимо выполнить при обновлении схемы. При создании базиса, достаточно удобно использовать инструмент SQL diff, для того чтобы убедиться, в идентичности базиса базе данных, созданной при запуске предыдущего базиса и всех скриптов обновления.

№2: Скрипты изменений, которые многие инструменты создают, в моём случае часто не работают в связи с размером баз данных с которыми я работаю. Некоторые из этих скриптов будут работать в течение многих часов. Большинство скриптов изменения являются написанными от руки с любовью и заботой. Это здорово, что-бы в команде было несколько разработчиков, хорошо разбирающихся в SQL, кончно я понимаю, что не у каждой команды есть эта роскошь и у меня, честно говоря, нет хорошего ответа как работать в этом случае.

Я думаю, что цикл статей окончен… На данный момент.

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

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

Моей целью в написании этих постов было заставить людей, которые не контролируют их версию базы данных, чтобы думать о запуске. Если ваша база данных уже находится в системе контроля версий, я надеюсь что эта серия постов помогла подтвердить ваш подход, или навеяла новые идеи. Возможно, у вас уже есть намного лучший процесс, то в этом случае вы должны попытаться написать статью о нём, потому что в интернете большой интерес к этой теме. А еще лучше - написать статью или книгу, но поторопись, мы должны услышать от вас!


comments powered by Disqus