Описание
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 позволяет откатывать изменения. Это можно сделать с помощью команд:
rollbackrollback-to-daterollback-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