Как пользоваться fly away
В этой статье я расскажу об одном из средств обеспечения версионности схем и управления миграциями БД — библиотеке Flyway. С поблемой версионности схемы базы данных рано или поздно приходится сталкиваться разработчикам любого приложения, опирающегося на СУБД. Увы, иногда эта проблема принимается в рассмотрение слишком поздно — например, если вопрос о внесении изменений в структуру базы встаёт, когда приложение уже находится в эксплуатации. Но и на этапе разработки контроль схемы базы данных причиняет не меньше проблем, чем все прочие аспекты версионности приложения: в отсутствие чёткой системы управления миграциями локальная, стендовая и эксплуатационная базы могут быстро «разъехаться», не предоставляя при этом никакой информации относительно своего текущего состояния.
Перзистенс-провайдеры штатно позволяют лишь в том или ином виде экспортировать актуальную объектную модель в виде схемы базы данных. Этот процесс может быть выполнен в режиме пересоздания (с полным удалением всей структуры), обновления (с внесением изменений) или сверки (без внесения изменений). Например, в Hibernate это делается с помощью инструмента hbm2ddl, работа которого может быть настроена единственным конфигурационным параметром в файле hibernate.cfg.xml или persistence.xml. Однако пересоздание (режим create) бывает нежелательным, если в базе уже есть данные, а обновление (режим update) вносит не все изменения, а только недеструктивные (например, не удаляются столбцы и таблицы) и не учитывает требующуюся реструктуризацию данных. Зачастую, если модель данных претерпела множество изменений, применить их к эксплуатационной базе бывает непросто, особенно если текущая версия базы неизвестна. Так или иначе, но приходится «опускаться» до SQL-скриптов — тут-то и встаёт вопрос управления версионностью.
Flyway
На главной странице проекта приведена наглядная таблица сравнения библиотеки с аналогичными решениями, и здесь основное внимание хочется обратить на богатую функциональность, работу с миграциями в виде простых SQL-файлов или Java-классов (последние по сути основываются на Spring JDBC Template) и поддержку нативного SQL популярных СУБД (Oracle PL/SQL, SQL Server T/SQL, хранимые процедуры MySQL и PostgreSQL).
Flyway хорошо интегрируется с Ant, Maven и инструментами командной строки, имеет API для программного вызова и интеграцию со Spring, работает со множеством СУБД. Я приведу пример подключения Flyway к уже существующему проекту, сборка которого основывается на Maven, а вызов Flyway производится при старте контекста Spring. В качестве базы данных в проекте используется MySQL.
Подключение Flyway к проекту
Для начала создадим папку db/migration в подкаталоге src/main/resources проекта: в ней будут храниться скрипты миграции. Поместим туда предварительно экспортированный скрипт базы данных — со всеми таблицами, представлениями, индексами и т.д. Назовём файл V1__Base_version.sql. Подробно соглашения по именованию миграций описаны в документации, пока достаточно сказать, что имя файла начинается с V, далее следует номер версии (с произвольным количеством точек-разделителей), двукратный символ подчёркивания и описание миграции.
Добавим в зависимости проекта (раздел dependencies) ядро библиотеки Flyway:
А в сборочные плагины (раздел build/plugins) — плагин Flyway:
Для запуска Flyway через плагин лучше создать отдельную учётную запись в базе. Можно указать пользователя и пароль для подключения к базе здесь же, в конфигурации плагина:
Или в параметрах командной строки:
Но более удобным способом, в случае сборки на Maven, будет помещение типовых параметров в файл настроек Maven (файл settings.xml) и дальнейшее использование их во всех аналогичных проектах:
Если необходимо инициализировать текущую базу с нуля, то можно выполнить её очистку. При этом всё содержимое базы будет удалено:
При успешном выполнении задачи база окажется пустой, а в логе Maven появятся следующие строки:
Если же база находится в актуальном состоянии (соответствует выгруженному ранее скрипту), необходимо выполнить задачу, которая создаст в ней необходимую для поддержания версионности структуру:
Далее можно убедиться, что в базе появилась таблица schema_version с единственной записью, соответствующей текущему состоянию базы:
Интеграцию Flyway с приложением выполним в виде бина Spring, стартующего перед entityManagerFactory:
После запуска приложения на чистой базе она будет инициализирована скриптом V1__Base_version.sql, кроме того, будет создана таблица schema_version. В логе при этом можно наблюдать следующее:
Если же приложение было запущено на базе, идентичной последней миграции, то никаких изменений в схеме не произойдёт, что будет отражено в логе приложения следующими строками:
В любом случае, при корректной интеграции Flyway база данных должна содержать приведённую выше таблицу schema_version с единственной записью.
Создание миграции
Создадим в папке db/migration файл с названием V2__Test_change.sql и со следующим содержимым:
После запуска приложения обнаружим в логе следующие строки:
И убедимся, что таблица test_table была успешно создана, а в таблице schema_version появилась запись о применённой миграции:
Откат миграции
Flyway, в отличие, например, от системы миграции в Rails, не поддерживает откат изменений. Авторы библиотеки мотивируют это тем, что после внесения деструктивных и необратимых изменений выполнить откат состояния базы так, чтобы все пропавшие или изменившиеся данные восстановились к прежнему состоянию, в общем случае невозможно. Вместо этого предлагается вполне разумный подход использования механизмов резервирования. Например перед применением очередной миграции можно делать выгрузку дампа или снимок базы (в зависимости от имеющегося в конкретной СУБД функционала резервирования).
Привет Хабровчане и Хабровчановки!
Хочу рассказать о очень удобном и полезном инструменте под названием FlyWay. На самом деле статьи уже были на нашем любимом ресурсе, но в последнее время произошли некоторые достаточно существенные изменения, поэтому свежая порция информации не помешает я думаю.
Что же такое FlyWay?
Как говорит официальная страница «Welcome to Flyway, database migrations made easy.», что не может быть неправдой.
Количество поддерживаемых баз довольно приятное:
- Oracle
- SQL Server
- SQL Azure
- DB2
- DB2 z/OS
- MySQL
- MariaDB
- PostgreSQL
- Redshift
- Vertica
- EnterpriseDB
- H2
- Hsql
- Derby
- SQLite
- SAP HANA
- solidDB
- Sybase ASE
- Phoenix
- Greenplum
- migrate — migrates the database
- clean — drops all objects in the configured schemas
- info — prints the details and status information about all the migrations
- validate — validates the applied migrations against the ones available on the classpath
- baseline — baselines an existing database, excluding all migrations up to and including baselineVersion
- repair — repairs the metadata table
Для подключения FlyWay к проекту в pom.xml необходимо добавить новую часть простынки, вида примерно такого:
Настроек для плагина кроме этих огромное количество, доступны в документации, я использую только эти на данный момент, ну и еще парочку. Кастомизировать можно фактически все что угодно, подключить несколько схем и тд и тп.
Далее, важно верное именование скриптов. Так как миграции происходят последовательно, необходимо сохранять версионирование. Имена должны иметь вид V1_1__some_text.sql для первого скрипта, далее для второго V1_2__else_text.sql для второго и так далее. Обязательно обратить внимание на двойное подчеркивание перед текстом, это необходимое требование к имени!
Собственно, подключили мы плагин, создали пару скриптов и к работе уже готовы.
Предположим, что проект начат, какие то данные залиты, хотим все привести в порядок и автоматически далее накатывать.
Приводим скрипты к описанному выше виду, проверяем их на работоспособность ( а как же без этого), далее делаем mvn flyway:clean и получаем чистую базу. Далее используем mvn flyway:migrate и вуаля, получаем ее в том виде, как было до clean.
Затем, по прошествии времени, появляется необходимость добавления данных. Если берем пример выше, у нас к примеру было 2 скрипта, создаем третий с именем V1_3_something.sql и снова проводим mvn flyway:migrate. Flyway определяет, что появился новый скрипт и донакатывает его на нашу базу.
Очень важно обратить внимание, что если были внесены изменения в V1_1 или V1_2, не произведены какие то действия, затем добавлено V1_3 и запущена миграция, то ничего не выйдет. Необходимо соблюдать неизменяемость предыдущих скриптов.
Конечно, в вышеописанной ситуации может помочь repair либо baseline, но не всегда, есть определенные ограничения накладываемые на базу данных, например первая строка официальной документации по repair сообщает нам условие «Remove failed migration entries (only for databases that do NOT support DDL transactions)». Важно обращать на это внимание.
На личном опыте, при использовании OracleBD при ошибке в накатке последнего скрипта помогает baseline.
На данный момент количество скриптов дошло в моем проекте до V3_21, первую цифру меняем в зависимости от проекту, вторую по количеству новых изменений. Проблем не возникает, если необходимо раскатать новое окружение, использую Jenkins, запуск Job и все. Естественно в pom.xml используются профили и их всего несколько — локальный хост, новый хост, обновление старого хоста. Достаточно быстро и удобно.
Вообще, как полагается у хороших людей, официальная документация, довольно подробная, с картинками, наглядно объясняющими что да как, да хорошими примерами, но для того, чтобы сделать первый шаг, описанного в статье будет уже достаточно.
Читайте также: