DBマイグレーション比較:Flyway vs Liquibase vs Alembic でスキーマをバージョン管理する
オープンソースラボ編集部 ・ 2026年6月14日
DBマイグレーション比較:Flyway vs Liquibase vs Alembic でスキーマをバージョン管理する
データベーススキーマの変更(カラム追加・インデックス作成・テーブル名変更)をバージョン管理してCI/CDパイプラインで安全に適用するツールがDBマイグレーションツールです。Flyway(Java/Go・SQLファースト)・Liquibase(Java・XML/YAML/SQL対応)・Alembic(Python/SQLAlchemy)の3つがOSSマイグレーションツールのデファクトスタンダードです。
DBマイグレーションツールを使う理由
- 再現性: 「本番のスキーマをstaging環境に完全再現」を自動化
- ロールバック: マイグレーション失敗時に前のバージョンに自動巻き戻し
- チーム協調: 複数開発者が同時にスキーマ変更を行う際の競合管理
- 監査: どのマイグレーションがいつ適用されたかの完全な履歴
主要ツールの概要
Flyway
2010年公開、Java製のOSSです。GitHubスター8k+。SQLファイルに連番を付けるだけでバージョン管理できるシンプルさが特徴です。V1__create_users.sql・V2__add_email_index.sqlのようなファイル名規則に従ってSQLを配置するとFlywayが順番に実行します。Docker・CLI・Maven/Gradle・Spring Boot統合が充実しています。
-- db/migration/V1__create_users_table.sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_users_email ON users(email);
-- db/migration/V2__add_user_status.sql
ALTER TABLE users
ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'active',
ADD COLUMN last_login_at TIMESTAMPTZ;
-- db/migration/V3__create_orders_table.sql
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
total NUMERIC(12,2) NOT NULL CHECK (total >= 0),
status VARCHAR(20) NOT NULL DEFAULT 'pending',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_status ON orders(status);
# docker-compose.yml - Flyway + PostgreSQL
version: "3.8"
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myapp
POSTGRES_PASSWORD: ${DB_PASSWORD}
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myapp"]
interval: 5s
timeout: 5s
retries: 5
flyway:
image: flyway/flyway:latest
command: migrate
environment:
FLYWAY_URL: jdbc:postgresql://db:5432/myapp
FLYWAY_USER: myapp
FLYWAY_PASSWORD: ${DB_PASSWORD}
FLYWAY_BASELINE_ON_MIGRATE: "true"
FLYWAY_VALIDATE_ON_MIGRATE: "true"
FLYWAY_LOCATIONS: filesystem:/flyway/sql
volumes:
- ./db/migration:/flyway/sql
depends_on:
db:
condition: service_healthy
# Flyway CLI コマンド
# マイグレーション適用
flyway migrate -url=jdbc:postgresql://localhost:5432/myapp -user=myapp -password=${DB_PASSWORD} -locations=filesystem:./db/migration
# マイグレーション状態確認
flyway info
# 検証(チェックサム不一致がないか確認)
flyway validate
# ロールバック(Flyway Pro機能 / コミュニティ版では手動undo SQL)
# db/migration/U3__create_orders_table.sql を作成してflyway undo
# GitHub Actions: マイグレーション自動適用
# .github/workflows/migrate.yml
# on: push to main / pull_request で flyway validate
Liquibase
2006年公開、Java製のOSSです。GitHubスター4.5k+。SQL・XML・YAML・JSON形式でchangelogを記述でき、データベース非依存(PostgreSQL・MySQL・Oracle・SQLite・MongoDB等)でマイグレーション定義を一元管理できます。ロールバック定義(<rollback>タグ)が標準搭載で本番事故対応に強みがあります。
# db/changelog/changelog-root.yaml
databaseChangeLog:
- include:
file: db/changelog/001-create-users.yaml
- include:
file: db/changelog/002-add-orders.yaml
# db/changelog/001-create-users.yaml
databaseChangeLog:
- changeSet:
id: 001-create-users
author: data-team
comment: ユーザーテーブルの作成
changes:
- createTable:
tableName: users
columns:
- column:
name: id
type: BIGINT
autoIncrement: true
constraints:
primaryKey: true
- column:
name: email
type: VARCHAR(255)
constraints:
nullable: false
unique: true
- column:
name: name
type: VARCHAR(100)
constraints:
nullable: false
- column:
name: created_at
type: TIMESTAMPTZ
defaultValueComputed: NOW()
constraints:
nullable: false
- createIndex:
indexName: idx_users_email
tableName: users
columns:
- column:
name: email
rollback:
- dropTable:
tableName: users
- changeSet:
id: 002-add-user-status
author: data-team
changes:
- addColumn:
tableName: users
columns:
- column:
name: status
type: VARCHAR(20)
defaultValue: active
constraints:
nullable: false
rollback:
- dropColumn:
tableName: users
columnName: status
Alembic
2011年公開(SQLAlchemy)、Python製のOSSです。GitHubスター2.5k+。PythonのSQLAlchemy ORMと統合されたマイグレーションツールで、Pythonコードでマイグレーションを記述できます。FastAPI・Django(django-alembic)・Flask-SQLAlchemyプロジェクトのデファクトマイグレーションツールです。
# alembic/versions/20240101_create_users.py
from alembic import op
import sqlalchemy as sa
revision = '001_create_users'
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
op.create_table(
'users',
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
sa.Column('email', sa.String(255), nullable=False),
sa.Column('name', sa.String(100), nullable=False),
sa.Column('status', sa.String(20), server_default='active', nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True),
server_default=sa.text('NOW()'), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email', name='uq_users_email'),
)
op.create_index('idx_users_email', 'users', ['email'])
def downgrade() -> None:
op.drop_index('idx_users_email', table_name='users')
op.drop_table('users')
# Alembic コマンド
pip install alembic sqlalchemy psycopg2-binary
# プロジェクト初期化
alembic init alembic
# 新しいマイグレーションを自動生成(モデルとDBの差分から)
alembic revision --autogenerate -m "create_users_table"
# マイグレーション適用
alembic upgrade head
# 特定バージョンへ
alembic upgrade 001_create_users
# ロールバック(1つ前へ)
alembic downgrade -1
# 状態確認
alembic current
alembic history --verbose
機能比較表
| 比較項目 | Flyway | Liquibase | Alembic |
|---|---|---|---|
| 記述形式 | SQL | SQL/XML/YAML | Python |
| 自動生成 | ❌ | ❌ | ✅(autogenerate) |
| ロールバック | △(Pro) | ✅ | ✅ |
| DB対応 | PostgreSQL/MySQL/Oracle等 | 同左+MongoDB | SQLAlchemy対応DB |
| Spring Boot統合 | ✅ | ✅ | ❌ |
| Python統合 | △ | △ | ✅ |
DBマイグレーションはDevOpsカテゴリ/categories/devopsのCI/CDパイプライン(GitHub Actions・GitLab CI)でデプロイ前に自動マイグレーションを実行するステップとして統合します。セキュリティカテゴリ/categories/securityのRow Level Security(RLS)ポリシーの追加・変更もマイグレーションスクリプトとして管理してバージョン履歴を保持します。
FAQ
Q. FlywayとLiquibaseはどう使い分けますか?
A. SQLしか使わない・シンプルさ優先ならFlyway、ロールバック定義を標準化したい・DB非依存で複数DBをサポートするならLiquibaseが向いています。Flywayの強み: ①SQLファイルを連番で置くだけなのでSQL経験者なら即日使える②Spring Bootのspring.flyway.enabled=trueで自動統合③ファイル名の規則(V・R・U prefix)でバージョン・反復・アンドゥを明確に分類。Liquibaseの強み: ①<rollback>タグでマイグレーションのロールバックSQLを必ず定義するチームルールを強制②XML/YAML形式でDB種別に依存しない記述(PostgreSQLからOracleへの移行も同一changelogで対応)③Diff機能(liquibase diff)で実際のDBスキーマとchangelogの乖離を検出。
Q. AlembicのautogenerateはどのようにDiffを検出しますか?
A. SQLAlchemyのモデル定義(Base.metadata)とデータベースの実際のスキーマを比較して差分を検出します。検出可能な変更: ①テーブルの追加・削除②カラムの追加・削除③カラムの型変更・nullable変更・server_default変更④主キー・ユニーク制約・外部キーの追加・削除⑤インデックスの追加・削除。autogenerateの注意点: ①カラムの型変更(VARCHAR(100)→VARCHAR(255)等)は検出されるが、DB型のエイリアス(TEXT≡VARCHAR等)で誤検知することがある②カスタム型(PostgreSQLのJSONB・ARRAY等)はinclude_objectフックでフィルタリングが必要③生成されたマイグレーションは必ず人間が確認してから本番適用する。
Q. 本番DBのマイグレーション中にダウンタイムを最小化するには?
A. ゼロダウンタイムマイグレーション(Online Schema Change)のパターンを使います。①展開: 新しいカラム/テーブルをNULL許容で追加(既存アプリは無視・新アプリは書き込み)②バックフィル: バッチでデータを移行(UPDATE users SET new_col = old_col WHERE id BETWEEN ? AND ?を小分けに実行)③切り替え: 新アプリをデプロイして新カラムを使用④クリーンアップ: 旧カラムを削除(この時点でダウンタイムゼロのまま完了)。ALTER TABLE users ADD COLUMNはPostgreSQL 9.6+で即座(ゼロロック)に実行できます。ALTER TABLE ... DROP COLUMNも即座ですが、インデックス再構築(CREATE INDEX CONCURRENTLY)や制約追加(ALTER TABLE ADD CONSTRAINT ... NOT VALID→VALIDATE CONSTRAINT)は時間がかかるためCONCURRENTLYオプションを活用します。
Q. Flywayで本番マイグレーションが失敗した時の対処法は?
A. flyway repairを使って壊れた状態を修正します。①Flywayはflyway_schema_historyテーブルに実行履歴を保存②マイグレーション失敗時はsuccess=falseのレコードが残り次回migrateが拒否される③flyway repairで失敗レコードを削除→問題のあるSQLを修正→再度migrateで続きから適用。Flyway Pro(有料)のundo機能なしでロールバックする手順: ①失敗したマイグレーションのロールバックSQLを手動実行②flyway repairで履歴を修正③正しいSQLでマイグレーションを再定義→migrate。本番での予防策: ①必ずflyway validateをデプロイ前CIで実行②staging環境で本番と同じDBスナップショットに対してマイグレーションを事前テスト。
まとめ
| ユースケース | 推奨ツール |
|---|---|
| SQLファースト・Spring Boot・シンプル運用 | Flyway |
| ロールバック定義必須・複数DB対応 | Liquibase |
| Python/SQLAlchemy・FastAPI・自動生成 | Alembic |