Подтвердить что ты не робот

Базы данных и "филиал"

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

Каждый раз, когда мы обновляем структуру базы данных, мы должны предоставить script для обновления базы данных от предыдущей версии до текущей.

Итак, в базе данных есть номер, который дал нам текущую версию, а затем наше программное обеспечение делает обновление, когда мы хотим использовать "старую" базу данных.

Проблема, с которой мы сталкиваемся, - это когда у нас есть ветки:

Когда мы создаем новую большую функцию, которая не будет доступна для пользователей (и не включена в выпуски), мы создаем ветку.

Основная ветвь (соединительная линия) будет объединена регулярно, чтобы гарантировать, что для создания бранча будут исправлены самые последние ошибки.

Вот несколько иллюстраций: enter image description here

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

Представьте, что при создании ветки мы имеем версию DB 17.

Затем мы создаем ветвь и делаем изменения в DB внешней линии. Теперь у DB есть версия 18.

Затем мы делаем изменение db на ветке. Поскольку мы знаем, что уже была новая версия "18", мы создаем версию 19 и обновление 18- > 19.

Затем соединительная линия объединяется в ветку.

В этот самый момент у нас могут быть некоторые обновления, которые никогда не будут выполняться.

Если кто-то обновил свою базу данных до слияния, его база данных будет отмечена как имеющая версию 19, обновление 17- > 18 никогда не будет выполнено.

Мы хотим изменить это поведение, но мы не можем найти, как:

Наши ограничения:

  • Мы не можем внести все изменения в одну ветвь
  • Иногда у нас есть не более двух ветвей, и мы можем только объединиться с соединительной линии до ветки функции до тех пор, пока функция не будет завершена.

Что мы можем сделать для обеспечения непрерывности между нашей ветвью базы данных?

4b9b3361

Ответ 1

Я думаю, что самый простой способ - использовать подход Ruby-on-rails. Каждое изменение БД представляет собой отдельный файл script, независимо от того, насколько он мал. Каждый script файл пронумерован, а когда вы выполняете обновление, вы просто запускаете каждый script из числа, которое ваша БД в настоящее время занимает до последнего.

На практике это означает, что ваша система версий DB перестает быть v18 до v19 и начинается с v18.0 до v18.01, затем v18.02 и т.д. То, что вы выпускаете клиенту, может быть свернуто в большой v19 upgrade script, но по мере развития вы будете делать много и много небольших обновлений.

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

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


edit: так что принципиально вы сначала должны избавиться от понятия использования обновления sdcript для перехода от версии к версии. Например, если вы начинаете с таблицы, а соединительная линия добавляет столбец A, а ветка добавляет столбец B, то вы объединяете магистраль в ветку - вы не можете реалистично "обновить" до версии с обоими, если номер версии ветки не больше, чем обновление соединительной линии script, и это не сработает, если вы впоследствии объедините магистраль в ветку. Поэтому вы должны отказаться от идеи "версии", которая применяется к ветвям развития. Единственный способ - это обновить каждое изменение независимо и отслеживать каждое изменение индивидуально. Затем вы можете сказать, что вам нужен "последний основной релиз плюс cola плюс colB" (по общему признанию, если вы объедините соединительную линию, вы можете взять текущую основную версию из магистрали независимо от ее v18 или v19, но вам все равно нужно применять каждое обновление ветки отдельно).

Итак, вы начинаете с trunk в DB v18. Разделите и внесите изменения. Затем вы объедините соединительную линию позже, где DB находится в v19. Ваши прежние изменения в ветке все равно должны применяться (или должны быть уже применены, но вам может понадобиться написать ветвь-обновление script со всеми изменениями ветвления в нем, если вы заново создаете свою БД). Обратите внимание, что ветвь вообще не имеет номера версии "v20", а изменения ветвей не создаются ни одним обновлением script, как у вас на соединительной линии. Вы можете добавить эти изменения, которые вы делаете на ветке, в виде единственного script, если хотите (или 1 script из "с момента слияния последнего сальдо" ) или столько маленьких скриптов. Когда ветка завершена, самая последняя задача состоит в том, чтобы выполнить все изменения БД, сделанные для ветки, и поместить их в script, которые могут быть применены к главному обновлению, и когда он будет объединен с trunk, этот script сливается в текущее обновление script, и номер версии DB набросился.

Существует альтернатива, которая может сработать для вас, но я обнаружил, что она немного шелушатся, когда вы пытаетесь обновить базы данных с данными, иногда просто не удалось выполнить обновление, и БД пришлось стереть и (что, если быть справедливым, вероятно, должно было произойти, если бы я использовал SQL-скрипты в то время). Это для использования проекта Visual Studio Database. Это сохраняет каждую часть схемы в виде файла, поэтому у вас будет 1 script за стол. Они будут скрыты от вас самой Visual Studio, которая покажет вам дизайнеров вместо сценариев, но они будут сохранены в виде файлов в контроле версий. VS может развернуть проект и попытаться обновить вашу БД, если он уже существует. Будьте осторожны с параметрами, многие по умолчанию говорят "drop and create" вместо использования alter для обновления существующей таблицы.

Эти проекты могут генерировать (в основном машиночитаемый) SQL script для развертывания, мы использовали для их создания и доставляли их команде DBA, которая не использовала VS и только принимала SQL.

И, наконец, Roundhouse, который я не использовал, но это может помочь вам стать новым обновителем "script". Это бесплатный проект, и я прочитал его более мощный и простой в использовании, чем проекты VS DB. Его средство управления версиями и изменениями DB, интегрируется с VS и использует SQL-скрипты.

Ответ 2

Мы используем следующую процедуру в течение примерно 1,5 лет. Я не знаю, было ли это наилучшим решением, но у нас не было никаких проблем с ним (за исключением некоторых человеческих ошибок в дельта файле, например, забыли USE -statement).

У него есть некоторые сходства с ответом, который дал Krumia, но он отличается тем, что в этом подходе выполняются только новые скрипты/файлы дельта смены. Это значительно облегчает запись этих файлов.

Файлы Delta​​strong >

Запишите все изменения DB, которые вы делаете для функции в дельта файле. Вы можете иметь несколько операторов в одном дельта файле или разделить их на несколько. После того, как он зафиксировал этот файл, он лучше всего (и после его объединения необходимо), чтобы начать новый, и оставить старое нетронутым.

Поместите все дельта файлы в один каталог и дайте им шаблон-имя, например YYYY-MM-DD-HH.mm.description.sql. Очень важно, чтобы вы могли сортировать их во времени (поэтому временная метка), чтобы вы знали, какой файл нужно выполнить в первую очередь. Кроме того, вы не хотите иметь конфликт слияния с этими файлами, чтобы он был уникальным (по всем веткам).

Слияние/вытягивать

Создайте слияние - script (для примера bash - script), который выполняет следующие действия:

  • Обратите внимание на текущий commit-hash
  • Сделайте фактическое слияние (или вытяните)
  • Получить список всех дельта файлов, добавленных с этим слиянием (git diff --stat $old_hash..HEAD -- path/to/delta-files)
  • Выполните эти дельта файлы в порядке, указанном меткой времени

Используя git, чтобы определить, какие файлы являются новыми (и, следовательно, какие действия не выполняются в текущей ветке), вы больше не привязаны к нумерации версий.

Переменные дельта файлы

Может случиться так, что в одном слиянии дельта файлы из разных ветвей могут быть "новыми для выполнения" и что эти файлы чередуются следующим образом:

  • 2014-08-04-дельта-из-feature_A.sql
  • 2014-08-05-дельта-из-feature_B.sql
  • 2014-08-06-дельта-из-feature_A.sql

Поскольку временная метка определяет порядок выполнения, сначала будет добавлено что-то из функции A, затем функция B, а затем обратно к функции A. Когда вы пишете правильные дельта файлы, которые исполняются самим/автономным, это не должно быть проблемой.

Ответ 3

Недавно мы начали использовать Sql Server Data Tools (SSDT), который заменил тип проекта Visual Studio Database, на версию, управляющую нашим SQL базы данных. Он создает проект для каждой базы данных, элементы для представлений и хранимых процедур и возможность создавать приложения уровня данных (DACPAC), которые могут быть развернуты к экземплярам SQL Server. SSDT также поддерживает Unit Testing и Статические данные и предлагает разработчикам возможность быстрого тестирования с использованием экземпляра LocalDB. Существует хороший обзор видео в тесте SSDT и гораздо больше ресурсов в Интернете.

В вашей ситуации вы должны использовать SSDT для управления объектами базы данных в управлении версиями вдоль вашего кода приложения, используя тот же процесс слияния, чтобы нажимать функции между ветвями. Когда придет время для обновления существующей установки, вы должны создать DACPAC и использовать Процесс обновления приложений уровня данных, чтобы применить изменения. В качестве альтернативы вы также можете использовать инструменты синхронизации базы данных, такие как DBGhost или RedGate применить обновления к существующей схеме.

Ответ 4

Требуется миграция базы данных. Для многих платформ есть плагины. Например, CakePHP использует плагин CakeDC для управления. Вот некоторые общие инструменты: http://en.wikipedia.org/wiki/Schema_migration#Available_Tools.

Если вы хотите сворачивать свои собственные, возможно, вместо сохранения текущей версии БД в базе данных, вы сохраняете список исправлений. Поэтому вместо таблицы version с одной строкой со значением 19 вместо этого у вас есть таблица patches с несколькими строками:

Patches
1
2
3
4
5
8

Глядя на это, вам нужно применить патчи 6 и 7.

Ответ 5

Эта идея может работать или не работать, но чтение о вашей работе до сих пор, и предыдущий ответ выглядит как изобретать колесо. "Колесо" - это управление источником, с его функциями отслеживания ветвления, слияния и отслеживания версий.

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

Замените свой метод следующим: Поддерживайте только один (и только один!) SQL файл, который хранит всю команду DDL для создания таблиц, индексов и т.д. с нуля. Вам нужно добавить новое поле? Добавьте строку "ALTER TABLE" в ваш файл SQL. Таким образом, ваш инструмент управления исходным кодом будет управлять вашей схемой базы данных, и каждая ветка может иметь другую.

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

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

EDIT: Я потратил некоторое время на поиск материалов для поддержки этого подхода. Вот тот, который выглядит особенно хорошо, с проверенной репутацией:

Управление версиями схемы базы данных 101

Вы видели эту ситуацию раньше?

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

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

  • Поскольку он может быть реализован с помощью ANSI SQL, он не агностик базы данных
  • Поскольку он зависит от сценариев, он требует незначительного управления хранением и может вписываться в текущее управление версиями кода Программа

Ответ 6

Я просто наткнулся на старую статью, написанную в 2008 году Джеффом Этвудом; надеюсь, это по-прежнему актуально для вашей проблемы.

Получите свою базу данных под контролем версий

В нем упоминаются пять частей, написанных К. Скоттом Алленом:

Ответ 7

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


Ответ заключается в применении изменений базы данных с помощью перераспределяемых сценариев изменений.

  • Все изменения, независимо от того, какая ветка она включена (даже в главном/соединительном канале), должны выполняться в отдельном script.
  • Последовательно создайте свои сценарии, чтобы новые из них сначала не выполнялись. Имея префикс с датой в формате YYYYMMDD для имени файла, сработал для нас.
  • Если это произойдет, это изменение внесено в исходный код, а не в базу данных. Вы можете иметь столько экземпляров/сборок для различных тегов/ветвей в VCS, сколько захотите. Например, отдельные живые сборки для каждой ветки.
  • Тогда вам нужно сделать сборку для каждого экземпляра (вероятно, каждый день). Строка должна извлекать файлы из соответствующей ветки и выполнять компиляцию/развертывание. Поскольку сценарии перераспределяются, старые сценарии не влияют на базу данных. В базу данных развернуты только последние изменения.

Но как сделать передислоцируемые скрипты?

Это вопрос, на который трудно ответить, поскольку вы не указали, какую базу данных вы используете. Поэтому я приведу вам пример о том, как это делает моя организация.

Позвольте мне привести простой пример: если нам нужно добавить столбец в определенную таблицу, мы не просто напишем ALTER TABLE ... ADD COLUMN .... Мы пишем код для добавления столбца, если и только если этот столбец не существует в данной таблице.

Теперь у нас есть отдельный API, который обрабатывает все, что проверяет код проверки работоспособности. Поэтому наши скрипты - это просто призывы к этим API. Вам придется писать свои собственные. Эти API на самом деле не так сложны (мы используем Oracle RDBMS). Но они дают нам огромный выигрыш в управлении версиями и развертывании.

Но, что только один сценарий, есть gazillion способы определения схемы могут изменить

Да, действительно. Тип данных столбца может измениться; Можно добавить новую таблицу; Столбец атрибутов можно объединить в первичный ключ (очень редко); Последовательности могут измениться; Ограничения; Иностранные ключи; Все они могут измениться.

Но получается, что все это может обрабатываться API со специальными привилегиями для чтения таблиц метаданных. Я не говорю, что это легко, но я говорю, что это единовременная стоимость.

Но как вы откатите изменение базы данных?

Мой личный опыт заключается в том, что если вы приложите некоторые реальные усилия для проектирования, прежде чем стучать на клавиатуру, чтобы писать операторы ALTER TABLE, этот сценарий встречается крайне редко. И если когда-либо есть откат, вы должны вручную обработать его. (например, вручную удалите добавленный столбец).

Обычно изменения в представлениях и хранимых процедурах довольно распространены, а изменения в определениях таблиц встречаются редко.

Построение базы данных

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

Развертывание базы данных script не должно начинаться с DROP DATABASE. В вашей базе данных есть много данных, которые использовались для модульных тестов. Если вы не сделаете действительно очень простую систему, эти данные будут полезны в будущем для тестирования. Ваши тестеры не будут слишком довольны добавлением десяти тысяч записей в различные таблицы каждый раз при обновлении базы данных.

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


Вы можете попробовать использовать схемы номеров версий, такие как 18.1-branchname и т.д. Но они действительно будут терпеть неудачу. Поскольку вы можете объединить свой источник, а не экземпляры.

Ответ 8

Существуют инструменты, специально разработанные для решения этих проблем.

Один DBSourceTools

DBSourceTools - это утилита GUI, помогающая разработчикам принести SQL Server базы данных под контролем источника. Мощный сценарий базы данных, код редактор, генератор sql и средство управления версиями базы данных. Сравните схемы, создавать скрипты diff, легко редактировать T-SQL. Лучше, чем управление Студия.

Другой: neXtep Designer

Дизайнер NeXtep - это интегрированная среда разработки для базы данных Разработчики. Основная концепция продукта - воспользоваться преимуществами управления версиями, чтобы вычислить инкрементные SQL-скрипты, которые вам нужны для обеспечения ваших разработок.

Этот проект направлен на создание платформы разработки, которая обеспечивает все инструментов, которые требуется разработчику базы данных при автоматизации задач генерируя поставки (= SQL, полученные в результате разработки).

Чтобы узнать больше о проблемах доставки обновлений баз, мы приглашаем вас прочитать статью "Обновление доставки базы данных", которая будет представить вам наше видение лучших и худших практик.

Ответ 9

Я думаю, что подход, который удовлетворит большинство ваших требований, включает концепцию "Рефакторинг базы данных".

Есть хорошая книга на эту тему Рефакторинг баз данных: эволюционный дизайн базы данных

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

В книге описывается рефакторинг базы данных с точки зрения:

  • Технология. Он включает полный исходный код для реализации каждого рефакторинга на уровне базы данных, и для большинства рефакторингов мы показать, как приложение изменится, чтобы отразить изменение в база данных. Примеры кода в Oracle, Java и Hibernate метаданные (рефакторинг легко перевести на другие среды, а иногда мы обсуждаем особенности, зависящие от поставщика, которые упростить некоторые рефакторинги).

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

  • Культура. Хотя технически просто реализовать индивидуальные рефакторинги и, очевидно, возможно (хотя и немного сложный), чтобы адаптировать внутренние процессы для поддержки базы данных рефакторинг, факт в том, что культурные проблемы в вашем организация, вероятно, окажется самым трудным препятствием для преодолеть.

Ответ 10

Я думаю, что то, как вы ставите проблему, невозможно решить, но если изменить часть вашего процесса, то есть решение. Давайте начнем с первой части: почему невозможно решить, используя только дельта. В следующем случае я предполагаю, что у вас есть основной багажник и две ветки dev-a и dev-b; обе ветки происходят из одного и того же момента.

Почему не удается работать

Скажем, Алиса добавляет дельта script в dev-a:

ALTER TABLE t1 (ALTER COLUMN col5 char(4))

и Bob добавить еще один script в dev-b

ALTER TABLE t1 (ALTER COLUMN col5 int)

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

Возможное решение

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

Пример

dev-a           *[email protected]@A1--------B.A2--*--B.A3--
               /                                   /
main -- B.0 --*--------------------------*--B.1---*----------
               \                        /
dev-b           *[email protected]*

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

Заключительный комментарий

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

Если вы выбираете только базовый уровень, у вас есть множество инструментов для поддержки.

Другим вариантом является сериализация работы с базой данных в целом или разделение схемы в отдельных областях с уникальными владельцами.