Описание
Liquibase - это библиотека с открытым исходным кодом для отслеживания, управления и применения изменений схемы базы данных. Является аналогом Git для баз данных. Вместо “коммитов” - changesets, представляющие наборы SQL команд на изменение БД.
Использование Liquibase в проекте позволяет отслеживать изменения схем БД, откатывать (rollback) базы до нужного состояния, облегчает развертывание скриптов на разных серверах.
Flexberry Designer поддерживает генерацию скриптов Liquibase для СУБД
PostgreSQL
иMicrosoft SQL Server
.
Установка Liquibase
Liquibase позволяет запускать команды через собственный CLI. В качестве альтернативы, можно запускать CLI в виде Docker контейнера.
Конфигурация Liquibase на проекте
- Инициализировать Liquibase в папке
SQL
проекта:liquibase init project
(следовать инструкциям на экране). При создании проекта требуется указать адрес БД в формате JDBC URL (например,jdbc:postgresql://localhost:5432/my-app-db
) и данные для подключения (логин и пароль).Настройки сохраняются в файл
liquibase.properties
- настройки в этом файле применяются по умолчанию. Этот файл может быть использован, чтобы задать подключение или схему, на которой будут запускаться скрипты. Более детально см. официальную документацию. - Добавить ссылки на папки со скриптами, которые необходимо отслеживать Liquibase:
- В файле
liquibase.properties
указать название корневого changelog:changeLogFile=liquibase.json
- В корневой changelog
liquibase.json
добавить ссылки на отслеживаемые папки:
{ "databaseChangeLog": [ { "includeAll": { "path": "относительный/путь/к/папкам/со/скриптами" } }, { "includeAll": //... } ] }
- В файле
- Если Liquibase устанавливается в существующее приложение и имеет скрипты, примененные вручную, необходимо отметить эти скрипты как выполненные:
liquibase changelog-sync
отметит существующие скрипты в папках как “применённые”, сохранив информацию о них в таблицуdatabasechangelog
; после этого командойupdate
будут применяться только новые скрипты
Рекомендации
Рекомендуется для liquibase указывать отдельную схему для хранения таблиц databasechangelog
и databasechangeloglock
:
- Указать название схемы
liquibase
для хранения внутренних таблиц Liquibase. В файлliquibase.properties
добавить строчку:liquibase.liquibaseSchemaName=liquibase
- Создать схему
liquibase
в БД (если скрипты будут применяться на разных БД, необходимо создать схему в каждой БД):
CREATE SCHEMA liquibase AUTHORIZATION postgres;
Создание скриптов
Для описания изменений в Liquibase используются текстовые файлы changelog. Файл содержит SQL-изменения базы данных в специальном liquibase-формате (xml, yaml, json, sql - на выбор). Рекомендуется использовать liquibase formatted sql, т.к. именно его генерирует Flexberry Designer.
Скрипты для Liquibase можно генерировать, используя Flexberry Designer
:
- Desktop версия
- Выбрать стадию -> Кликнуть правой кнопкой мыши ->
ORM
->SQL
->PostgreSQL
->Сгенерировать SQL для liquibase
- Выбрать стадию -> Кликнуть правой кнопкой мыши ->
- Flexberry Designer Enterprise
- Перейти в раздел
Генерация
-> для нужного типа хранилища отметить"Сгенерировать SQL для liquibase"
: - Нажать
"Скачать fdg файл"
. Данный файл будет иметь названиеGenConfig.fdg
, в нём появится опция"LiquibaseSQL": true
в разделе, который соответствует выбранной СУБД (в данном примере -PostgreSQL
). Если эта настройка в файле отсутствует, необходимо добавить её вручную:
- Перейти в раздел
"Storage": {
"PostgreSql": {
"LiquibaseSql": true,
...
}
}
Подробнее в практическом руководстве
Есть возможность написать скрипт самостоятельно. Для этого необходимо в начало обычного .sql
скрипта добавить следующие строчки:
--liquibase formatted sql
--changeset author:id
- гдеauthor
- автор изменений,id
- уникальный идентификатор набора изменений (рекомендуется использовать текущую дату и время).
Пример:
--liquibase formatted sql
--changeset aivanov:2023-01-24-11:30
CREATE TABLE example...
--changeset aivanov:2023-01-24-11:45
INSERT INTO example VALUES ...
Запуск команд Liquibase
После того, как конфигурация проекта Liquibase завершена, можно запускать команды. Команды запускаются с помощью CLI, который устанавливается вместе с Liquibase.
Команды можно запускать следующим образом:
liquibase update --log-level INFO
Команды необходимо запускать из папки, в которой был инициализирован liquibase (папка
SQL
).
Команда liquibase update
применит изменения, на которые есть ссылка в корневом changelog. Список полезных команд:
update
- применить все скриптыupdate-sql
- предпросмотр SQL для командыupdate
(не применяет скрипты)status
- отобразить количество ещё не запущенных скриптовvalidate
- проверить корректность скриптов
Запуск команд Liquibase через Docker
Есть возможность запускать команды Liquibase через Docker - т.е. без установки Liquibase CLI. Для этого необходимо использовать следующую команду:
docker run --rm -v ${PWD}/:/liquibase/changelog/ liquibase/liquibase --defaultsFile=/liquibase/changelog/liquibase.properties --changelog-file=liquibase.json --search-path=/liquibase/changelog/
Описание команды:
--rm
- удалить контейнер при завершении-v ${PWD}/:/liquibase/changelog/
- монтировать текущую директорию в папку/liquibase/changelog/
внутри образаliquibase/liquibase
- использовать официальный образ Liquibase CLI--defaultsFile=/liquibase/changelog/liquibase.properties
- путь до файла конфигурацииliquibase.properties
--changelog-file=liquibase.json
- путь до корневого changelog--search-path=/liquibase/changelog/
- путь, в котором будет производиться поиск changelogs
Если в контейнере папка
/liquibase/changelog/
становится пустой, возможно команда запущена из Windows через Git Bash. В таком случае, перед запуском необходимо задать ENV переменную MSYS_NO_PATHCONV=1. Переменную можно записать вsystem path
чтобы она не сбрасывалась.
Подробнее см. Использование Liquibase в Docker.
Откат изменений
Liquibase позволяет откатывать изменения. Это можно сделать с помощью команд:
rollback
rollback-to-date
rollback-count
(см. rollback).
Использование скриптов в нескольких БД
В приложении может потребоваться использовать несколько баз данных или развёртывать скрипты на разных БД (или разных схемах одной БД). Для этого можно воспользоваться контекстами в Liquibase.
Контекст - это группа, в которую помещаются changelogs для того, чтобы фильтровать скрипты по контексту и применять только нужные изменения (подробнее). Можно применить скрипты из контекста на определённой БД.
- Каждый скрипт из проекта может быть отнесен к своему контексту.
Чтобы отнести файл/папку к контексту, необходимо добавить параметр contextFilter
в changelog:
"includeAll": {
"path": "путь/к/папке/со/скриптами",
"contextFilter": "название_контекста"
}
Параметр задаёт, к какому контексту отнести нужный файл/папку.
- Скрипты из контекста можно применить на другой БД и другой схеме.
Следующие параметры могут быть использованы, чтобы применить скрипты на нужной БД:
--contexts контекст
- запустить командуliquibase
только по скриптам из указанного контекста;--url=jdbc:postgresql://адрес:порт/название_бд
- применить скрипты на указанной БД;--default-schema-name схема
- применить скрипты на указанной схеме БД.
Пример. Приложение имеет 2 БД -
core
(основную) иstorm
(для хранения полномочий и настроек). Чтобы применять скрипты на двух базах, необходимо:
- создать 2 папки:
/SQL/app
- для скриптов основного приложения;/SQL/storm
- для скриптов полномочий.- отнести папки к своему контексту (см. раздел использование нескольких БД):
/SQL/app
- к контекстуcore
,/SQL/storm
- к контекстуstorm
.- запустить команду
liquibase update --contexts storm --url=jdbc:postgresql://localhost:5432/storm
- это применит скрипты полномочий на БДstorm
- запустить команду
liquibase update --contexts >core --url=jdbc:postgresql://localhost:5432/app
- это применит скрипты приложения на БДcore
.
Чтобы облегчить процесс обновления, можно написать cmd
или sh
скрипт, который будет подставлять нужный url БД в зависимости от переданного контекста. Вызывать его, например, так: ./liquibase.sh update storm
- без необходимости прописывать url вручную. Пример такого скрипта:
#!/bin/bash
# Вспомогательный скрипт для запуска команд liquibase.
# Автоматически подставляет url нужной базы в зависимости от контекста.
#
# Использование:
# ./liquibase.sh <команда_liquibase> <название контекста (базы)>, например: ./liquibase.sh status storm
# Запуск в режиме Docker: добавьте опцию --docker
# P.S. Если <название контекста> не передано - скрипт будет применён на всех контекстах (базах) по очереди.
script_dir="$(cd "$(dirname "$0")" && pwd)"
env_file="$script_dir/liquibase.env"
# Загрузим ENV переменные из файла, которые ещё не были установлены:
source liquibase.env
contexts=(core storm) # доступные контексты
contextArgs=()
# Проверка, является ли переданное значение одним из доступных контекстов
isContext() {
if [[ " ${contexts[@]} " =~ " ${1} " ]]; then
return 1
else
return 0
fi;
}
# Проверка наличия опции в списке аргументов
check_option() {
local option=$1
shift
for arg in "$@"; do
if [[ "$arg" == "$option" ]]; then
return 1 # Опция найдена
fi
done
return 0
}
# Проверяем наличие опции --docker
check_option "--docker" "$@"
dockerMode=$?
filtered_arguments=()
# Обрабатываем переданные контексты
for arg in "$@"; do
isContext "$arg"
if [ $? = 1 ]; then
contextArgs+=("$arg")
elif [ $arg != '--docker' ]; then
filtered_arguments+=("$arg")
fi
done
# Если контексты не переданы, используем все доступные
if [ ${#contextArgs[@]} -eq 0 ]; then
contextArgs=("${contexts[@]}")
fi
for context in "${contextArgs[@]}"; do
# Переключаем в режим docker если передан параметр --docker:
if [ "$dockerMode" = 1 ]; then
export MSYS_NO_PATHCONV=1 # нужен чтобы пофиксить запуск через Git Bash на Windows
liquibaseCmd="docker run --rm -v ${PWD}/:/liquibase/changelog/ liquibase/liquibase --defaultsFile=/liquibase/changelog/liquibase.properties --changelog-file=liquibase.json --search-path=/liquibase/changelog/"
else
liquibaseCmd="liquibase"
fi
# Задаём БД в зависимости от контекста:
if [ "$context" = "storm" ]; then
database=$STORM_JDBC_URL
elif [ "$context" = "core" ]; then
database=$CORE_JDBC_URL
fi;
echo -e "Запускаем $1 на БД $context... \n"
# Запускаем команду:
echo "$liquibaseCmd $1 --contexts $context --url=$database ${filtered_arguments[@]:1}"
$liquibaseCmd $1 --contexts $context --url=$database ${filtered_arguments[@]:1}
# Завершаем выполнение на первом исключении:
if [ $? = 1 ]; then
exit 1
fi
echo ""
done
exit 0
Для работы скрипта необходим файл liquibase.env:
CORE_JDBC_URL=jdbc:postgresql://localhost:5432/app
STORM_JDBC_URL=jdbc:postgresql://localhost:25432/storm