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

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

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

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

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

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

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

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


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


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

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


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

14 ответов

Решение

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

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

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

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

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

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

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

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

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

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

  • Назовите ваши базы данных следующим образом - db_dev, db_test, db_qa, db_prod (Очевидно, вы никогда не должны жестко кодировать имена БД
  • Таким образом, вы сможете развернуть даже разные типы БД на одном физическом сервере (я не рекомендую этого, но вам, возможно, придется... если ресурсы ограничены)
  • Убедитесь, что вы сможете перемещать данные между этими автоматическими
  • Отделите сценарии создания БД от совокупности = всегда должна быть возможность воссоздать БД с нуля и заполнить ее (из старой версии БД или из внешнего источника данных
  • не используйте строки кода с жестким кодом в коде (даже не в файлах конфигурации) - используйте в файлах конфигурации шаблоны строк подключения, которые вы заполняете динамически, каждая реконфигурация application_layer, которая требует перекомпиляции, BAD
  • используйте версионность баз данных и версионность объектов БД - если вы можете себе это позволить, используйте готовые продукты, если не разрабатываете что-то самостоятельно
  • отслеживать каждое изменение DDL и сохранять его в какой-либо таблице истории ( пример здесь)
  • ЕЖЕДНЕВНЫЕ резервные копии! Проверьте, насколько быстро вы сможете восстановить что-то потерянное из резервной копии (используйте автоматические сценарии восстановления
  • даже у вашей базы данных DEV и PROD точно такой же сценарий создания, у вас будут проблемы с данными, поэтому позвольте разработчикам создать точную копию prod и поиграть с ней (я знаю, что я получу минусы для этого, но изменения в мышление и бизнес-процесс обойдутся вам гораздо дешевле, когда дерьмо попадет в фанат, поэтому заставьте кодеров легально подписывать все, что он делает, но убедитесь, что это

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

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

  • 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 в ветви. ARGH!

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

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

У нас очень похожая настройка на ОП.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. для каждой схемы дб получаем схему ддлс
  2. поставить его под версию контроля

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

Другие вопросы по тегам