Как вы управляете базами данных в процессе разработки, тестирования и производства?

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

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

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

У нас есть тестовый (виртуальный) сервер, на котором работают «кандидаты на выпуск». Развертывание на тестовом сервере в настоящее время является очень ручным процессом и обычно включает в себя загрузку последней версии SQL из SVN и ее настройку. Кроме того, данные на тестовом сервере противоречивы. В итоге вы получаете все тестовые данные, которые последний разработчик зафиксировал на своем сервере песочницы.

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

Если бы проблема заключалась только в схеме, это было бы проще, но в базе данных есть «базовые» данные, которые также обновляются во время разработки, такие как метаданные в таблицах безопасности и разрешений.

Это самый большой барьер, который я вижу на пути к непрерывной интеграции и одношаговой сборке. Как вы ее решаете?


Последующий вопрос: как отслеживать версии базы данных, чтобы знать, какие сценарии запускать для обновления данного экземпляра базы данных? Таблица версий, подобная той, которую упоминает Лэнс, ниже стандартной процедуры?


Спасибо за ссылку на Тарантино. Я не нахожусь в среде .NET, но нашел их вики-страницу DataBaseChangeMangement очень полезной. Особенно эта презентация PowerPoint (.ppt)

Я собираюсь написать сценарий Python, который проверяет имена *.sql сценариев в заданном каталоге по таблице в базе данных и запускает те, которых там нет, по порядку на основе целого числа, образующего первую часть имени файла. Если это довольно простое решение, как я подозреваю, я опубликую его здесь.


У меня для этого есть рабочий сценарий. Он обрабатывает инициализацию БД, если она не существует, и при необходимости запускает сценарии обновления. Также есть переключатели для очистки существующей базы данных и импорта тестовых данных из файла. Это около 200 строк, поэтому я не буду публиковать его (хотя могу выложить его на pastebin, если будет интерес).

Ответов (14)

Решение

Есть пара хороших вариантов. Я бы не стал использовать стратегию «восстановления из резервной копии».

  1. Запишите все изменения схемы и пусть ваш CI-сервер запускает эти сценарии в базе данных. Имейте таблицу версий для отслеживания текущей версии базы данных и выполняйте сценарии только в том случае, если они предназначены для более новой версии.

  2. Используйте решение для миграции. Эти решения различаются в зависимости от языка, но для .NET я использую Migrator.NET. Это позволяет вам обновлять вашу базу данных и переходить от одной версии к другой. Ваша схема указана в коде C#.

У нас очень похожая установка на OP.

Разработчики разрабатывают виртуальные машины с частными базами данных.

[Разработчики скоро перейдут в частные филиалы]

Тестирование проводится на разных машинах (фактически в виртуальной машине, размещенной на сервере) [Скоро будет запущено сервером Hudson CI]

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

Затем запустите модульные и системные тесты.

Производство предоставляется клиентам в качестве установщиков.

Что мы делаем:

Берем дамп схемы нашей БД песочницы. Затем дамп данных sql. Мы отличаемся от предыдущей базовой линии. эта пара дельт предназначена для обновления n-1 до n.

настраиваем дампы и дельты.

Итак, чтобы установить версию N CLEAN, мы запускаем дамп в пустую базу данных. Чтобы исправить, примените промежуточные пластыри.

(Юха упомянул, что идея Рейла о наличии таблицы, в которой записана текущая версия БД, является хорошей и должна сделать установку обновлений менее сложной.)

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

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

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

Если вы работаете в среде .NET, тогда решение - Tarantino (заархивировано) . Он обрабатывает все это (включая то, какие сценарии sql устанавливать) в сборке NANT.

Посмотрите, как это делает Ruby on Rails.

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

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

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

  • dbChanges_1.sql
  • dbChanges_2.sql
  • ...
  • dbChanges_n.sql

Это работало достаточно хорошо, пока мы не начали поддерживать две линии разработки: магистраль / магистраль для новой разработки и ветвь обслуживания для исправлений ошибок, краткосрочных улучшений и т. Д. Неизбежно возникла необходимость внести изменения в схему в ветке. К этому моменту у нас уже был dbChanges_n + 1.sql в магистрали, поэтому в итоге мы использовали такую ​​схему:

  • dbChanges_n.1.sql
  • dbChanges_n.2.sql
  • ...
  • dbChanges_n.3.sql

Опять же, это работало достаточно хорошо, пока однажды мы не посмотрели и не увидели 42 дельта-скрипта в основной строке и 10 в ветке. АРГХ!

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

Так что меня это тоже не устраивает. Мне очень нравится концепция миграции с Rails. Я очень увлекся LiquiBase . Он поддерживает концепцию инкрементного рефакторинга базы данных. На него стоит взглянуть, и я скоро рассмотрю его подробно. У кого-нибудь есть опыт работы с этим? Мне было бы очень любопытно узнать о ваших результатах.

Ознакомьтесь с dbdeploy , уже доступны инструменты Java и .net, вы можете следовать их стандартам для макетов файлов SQL и таблицы версий схемы и написать свою версию python.

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

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

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

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

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

Я написал инструмент, который (подключившись к Open DBDiff ) сравнивает схемы базы данных и предлагает вам сценарии миграции. Если вы сделаете изменение, которое удаляет или изменяет данные, оно выдаст ошибку, но предоставит предложение для сценария (например, когда столбец отсутствует в новой схеме, он проверит, был ли столбец переименован, и создаст xx - сгенерированный script.sql.suggestion, содержащий оператор переименования).

http://code.google.com/p/migrationscriptgenerator/ Боюсь, только SQL Server :( Это тоже довольно альфа, но ОЧЕНЬ низкое трение (особенно если вы объедините его с Tarantino или http://code.google .com / p / simplescriptrunner / )

Я использую его как проект сценариев SQL в вашем .sln. У вас также есть локальная база данных db_next, в которую вы вносите изменения (используя Management Studio или NHibernate Schema Export или LinqToSql CreateDatabase или что-то в этом роде). Затем вы выполняете migrationscriptgenerator с базами данных _dev и _next, который создает. сценарии обновления SQL для миграции.

Книга « Рефакторинг баз данных: эволюционный дизайн баз данных» может дать вам некоторые идеи о том, как управлять базой данных. Краткую версию можно также прочитать на http://martinfowler.com/articles/evodb.html.

В одном проекте PHP + MySQL у меня был номер версии базы данных, хранящийся в базе данных, и когда программа подключается к базе данных, она сначала проверяет версию. Если программе требуется другая версия, она откроет страницу для обновления базы данных. Каждое обновление указывается в коде PHP, который изменяет схему базы данных и переносит все существующие данные.

  • Назовите свои базы данных следующим образом - dev_<<db>> , tst_<<db>> , stg_<<db>> , prd_<<db>>(Очевидно, вам никогда не следует жестко кодировать имена db
  • Таким образом, вы сможете развернуть даже разные типы баз данных на одном физическом сервере (я не рекомендую это, но вам, возможно, придется ... если ресурсы ограничены)
  • Убедитесь, что вы сможете автоматически перемещать данные между ними.
  • Отделите сценарии создания базы данных от совокупности = всегда должна быть возможность воссоздать базу данных с нуля и заполнить ее (из старой версии базы данных или внешнего источника данных.
  • не используйте жестко запрограммированные строки подключения в коде (даже не в файлах конфигурации) - используйте в файлах конфигурации шаблоны строк подключения, которые вы заполняете динамически, каждая реконфигурация application_layer, которая требует перекомпиляции, является ПЛОХОЙ
  • используйте управление версиями базы данных и управление версиями объектов базы данных - если вы можете себе это позволить, используйте готовые продукты, если не разрабатываете что-то самостоятельно
  • отслеживать каждое изменение DDL и сохранять его в некоторой таблице истории ( пример здесь )
  • ЕЖЕДНЕВНОЕ резервное копирование! Проверьте, насколько быстро вы сможете восстановить что-то потерянное из резервной копии (используйте сценарии автоматического восстановления
  • даже ваша база данных DEV и PROD имеют один и тот же сценарий создания, у вас будут проблемы с данными, поэтому позвольте разработчикам создать точную копию prod и поиграть с ней (я знаю, что получу минусы для этого, но измените образ мышления и бизнес-процесс будут стоить вам намного меньше, когда дерьмо попадет в вентилятор - так что заставьте кодировщиков делать подстрочные индексы юридически все, что они делают, но убедитесь, что это

Мы используем командную строку mysql-diff : она выводит разницу между двумя схемами базы данных (из живой БД или скрипта) как скрипт ALTER. mysql-diff выполняется при запуске приложения, и если схема изменилась, он сообщает разработчику. Таким образом, разработчикам не нужно писать ALTER вручную, обновления схемы происходят полуавтоматически.

Для базы данных Oracle мы используем инструменты oracle-ddl2svn .

Этот инструмент автоматизировал следующий процесс

  1. для каждой схемы db получить схему ddls
  2. поместите это под версией contol

изменения между экземплярами разрешаются вручную