AI

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.sqlV2__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

機能比較表

比較項目FlywayLiquibaseAlembic
記述形式SQLSQL/XML/YAMLPython
自動生成✅(autogenerate)
ロールバック△(Pro)
DB対応PostgreSQL/MySQL/Oracle等同左+MongoDBSQLAlchemy対応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型のエイリアス(TEXTVARCHAR等)で誤検知することがある②カスタム型(PostgreSQLのJSONBARRAY等)は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 VALIDVALIDATE 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

関連外部リソース

他の記事も読む

Let's Build Together

OSS導入、自社だけで悩まない。

ツール選定から構築・運用・AI活用まで、オープンソースラボ運営元のClasslessが伴走します。初回のご相談は無料です。