В чем разница между Flyway и Liquibase?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Разница между Flyway и Liquibase
Краткое сравнение
| Критерий | Flyway | Liquibase |
|---|---|---|
| Язык | SQL (native) | XML, YAML, JSON, SQL |
| Версионирование | Простое (V1, V2, V3) | Более гибкое (changeset'ы) |
| Откат | Только undo scripts | Встроенный откат |
| Сложность | Простая, понятная | Более мощная, сложнее |
| Разработчик | Axel Fontaine | Liquibase Inc. |
| Community | Активное | Очень активное |
| Enterprise | Бесплатен | Есть платная версия |
Определение
Flyway
Flyway — простой инструмент версионирования БД на native SQL. Использует файлы с именами вроде V1__Initial_schema.sql, V2__Add_users_table.sql.
Философия: "Keep it simple" — просто SQL файлы, простой контроль.
Liquibase
Liquibase — мощный инструмент миграций БД с поддержкой multiple форматов (XML, YAML, SQL). Использует концепцию changesets с возможностью отката и условного выполнения.
Философия: "Database agnostic" — одна миграция работает на PostgreSQL, MySQL, Oracle и т.д.
Структура файлов
Flyway
Проста и понятна:
src/main/resources/db/migration/
├── V1__Initial_schema.sql
├── V2__Add_users_table.sql
├── V3__Add_email_column.sql
└── V4__Create_indexes.sql
Внутри файла — pure SQL:
-- V1__Initial_schema.sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id),
amount DECIMAL(10, 2)
);
Liquibase
Могу использовать разные форматы. XML пример:
<!-- db/changelog/db.changelog-master.xml -->
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.0.xsd">
<changeSet id="1" author="john">
<createTable tableName="users">
<column name="id" type="INT" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="name" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="email" type="VARCHAR(255)">
<constraints unique="true"/>
</column>
</createTable>
</changeSet>
<changeSet id="2" author="john">
<createTable tableName="orders">
<column name="id" type="INT" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="user_id" type="INT">
<constraints foreignKeyName="fk_user" references="users(id)"/>
</column>
<column name="amount" type="DECIMAL(10,2)"/>
</createTable>
</changeSet>
</databaseChangeLog>
YAML пример (более читаемо):
# db/changelog/db.changelog-master.yaml
databaseChangeLog:
- changeSet:
id: 1
author: john
changes:
- createTable:
tableName: users
columns:
- column:
name: id
type: INT
autoIncrement: true
constraints:
primaryKey: true
- column:
name: name
type: VARCHAR(255)
constraints:
nullable: false
- column:
name: email
type: VARCHAR(255)
constraints:
unique: true
- changeSet:
id: 2
author: john
changes:
- createTable:
tableName: orders
columns:
- column:
name: id
type: INT
autoIncrement: true
constraints:
primaryKey: true
- column:
name: user_id
type: INT
constraints:
foreignKeyName: fk_user
references: users(id)
- column:
name: amount
type: DECIMAL(10,2)
Практические примеры
Flyway в Spring Boot
# application.yml
spring:
flyway:
baseline-on-migrate: true # Инициализировать baseline на пустой БД
baseline-version: 0
out-of-order: false # Не позволять out-of-order миграции
locations:
- classpath:db/migration
// pom.xml
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>9.16.3</version>
</dependency>
При запуске приложения Flyway автоматически:
- Сканирует
/db/migration - Находит новые V* файлы
- Запускает их по порядку
- Записывает информацию в
flyway_schema_historyтаблицу
Liquibase в Spring Boot
# application.yml
spring:
liquibase:
change-log: classpath:db/changelog/db.changelog-master.yaml
enabled: true
// pom.xml
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.20.0</version>
</dependency>
Откаты и отмены
Flyway (Undo скрипты)
Для отката нужны отдельные файлы:
src/main/resources/db/migration/
├── V1__Initial_schema.sql
├── U1__Initial_schema.sql ← Undo скрипт!
├── V2__Add_users_table.sql
└── U2__Add_users_table.sql ← Undo скрипт!
-- U2__Add_users_table.sql (Откат для V2)
DROP TABLE IF EXISTS orders;
Откат командой:
flyway undo
Liquibase (Встроенный откат)
Oткат встроен в changeset'ы:
<changeSet id="2" author="john">
<createTable tableName="orders">
<!-- ... -->
</createTable>
<!-- Liquibase может автоматически сгенерировать undo -->
<rollback>
<dropTable tableName="orders"/>
</rollback>
</changeSet>
Откат командой:
liquibase rollback-count --count=1
Условные миграции
Flyway (Сложнее)
Фlyway не имеет встроенной поддержки условных миграций. Нужен workaround:
-- V3__Add_feature_X.sql
-- Не могу проверить in SQL, нужно делать на уровне приложения
ALTER TABLE users ADD COLUMN feature_flag BOOLEAN DEFAULT false;
Liquibase (Встроенная поддержка)
можно использовать preconditions:
<changeSet id="3" author="john">
<preConditions onFail="MARK_RAN">
<!-- Проверяй, есть ли эта таблица -->
<not>
<tableExists tableName="audit_log"/>
</not>
</preConditions>
<createTable tableName="audit_log">
<column name="id" type="INT" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
</createTable>
</changeSet>
Поддержка разных БД
Flyway
Делает большую часть работы, но иногда нужны specific файлы:
src/main/resources/db/migration/
├── V1__Init.sql ← Universal
├── V2__Index_postgres.sql ← Только для PostgreSQL
└── V2__Index_mysql.sql ← Только для MySQL
Средезва:
flyway.sql-migration-suffixes=.sql
flyway.clean-disabled=false
Liquibase
Лучше поддерживает DB-specific синтаксис:
<changeSet id="4" author="john" dbms="postgresql">
<sql>
CREATE INDEX idx_user_email ON users(email);
</sql>
</changeSet>
<changeSet id="5" author="john" dbms="mysql">
<sql>
CREATE INDEX idx_user_email ON users(email(50));
</sql>
</changeSet>
Когда использовать что
Используй Flyway, если:
✅ Проект простой ✅ Разработчики знают SQL хорошо ✅ Не нужны сложные условные миграции ✅ Хочешь простоту и скорость ✅ Вся БД одного типа (все PostgreSQL)
// Пример: Стартап, простая БД
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
// Flyway стартует автоматически
}
}
Используй Liquibase, если:
✅ Проект большой и сложный ✅ Нужны условные миграции ✅ Мультибаза (PostgreSQL в dev, Oracle в prod) ✅ Нужна история с автоматическим откатом ✅ Команда многоуровневая
// Пример: Enterprise приложение
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
// Liquibase с preconditions и rollback'ами
}
}
В проекте PrepBro
По конфигу видно, что используется Goose (не Flyway и не Liquibase), но если выбирать:
- Для стартапа/MVP: Flyway (простая, быстрая)
- Для масштабирования: Liquibase (гибкая, условная логика)
Итоговый ответ
Flyway:
- Простая и понятная
- Использует native SQL
- Нет встроенного отката (нужны undo скрипты)
- Лучше для простых проектов
Liquibase:
- Более мощная и гибкая
- Поддерживает XML, YAML, JSON
- Встроенный откат и условные миграции
- Лучше для больших проектов и сложных сценариев
Выбор зависит от сложности проекта и требований к миграциям.