DBAtlas · データベース運用アトラス

スキーママイグレーションの CI/CD (Flyway/Liquibase)

症状

目標: データベーススキーマの変更をバージョン管理されたマイグレーションファイルで管理し、Flyway または Liquibase を使って CI/CD 内で自動的かつ制御された形で適用する。

1. バージョン付きのマイグレーションファイルを作成する (Vxxx__name.sql)

すべてのスキーマ変更を、増加するバージョン番号付きの名前のファイルに書く。Flyway の規約は V<version>__<description>.sql である (例: V1__initial_schemas.sql、V2__orders_table.sql)。これらのファイルは Git で管理され、バージョン順に適用される。適用済みのマイグレーションは追跡テーブル (Flyway では flyway_schema_history) に記録されるため、各マイグレーションは正確に 1 回だけ実行される。

PostgreSQL

-- V2__orders_table.sql
CREATE TABLE orders (
  id       bigserial PRIMARY KEY,
  amount    numeric(12,2) NOT NULL,
  created_at   timestamptz DEFAULT now()
);

2. チェックサムで不変性を維持する

Flyway/Liquibase は適用済みの各マイグレーションのチェックサムを保存する。適用済みのファイルを後から編集するとチェックサムが一致しなくなり、ツールはエラーになる。ルール: 適用済みのマイグレーションは決して編集しないこと。修正は新しいバージョンのファイルで行う。これによりすべての環境 (dev/staging/prod) が同じ履歴を共有することが保証される。

PostgreSQL

# repair on checksum mismatch (use with care):
flyway repair
# the right way: add the change in a new Vx file

3. 既存のデータベースをベースライン化する

履歴のない、すでにデータが入ったデータベースにマイグレーションツールを導入する場合は baseline を使う。現在の状態を「開始バージョン」として扱い、既存のオブジェクトを再作成しようとしない。baselineVersion より後のマイグレーションが適用される。一から構築する環境ではベースラインは不要で、マイグレーションは V1 から実行される。

PostgreSQL

flyway baseline -baselineVersion=1 -baselineDescription="existing schema"

4. CI パイプラインで自動的にマイグレーションする

CI のステップでマイグレーションツールを実行し、テスト用とステージング用のデータベースに変更を自動的に適用する。migrate コマンドは新しい (未適用の) ファイルのみを実行し、冪等である。まず一時的な (エフェメラルな) データベースにマイグレーションを適用して検証すると、壊れた SQL が本番に到達する前に検出できる。スキーマはアプリケーションコードのデプロイより前にマイグレーションする必要がある (後方互換の変更で)。

PostgreSQL

# CI step (Flyway)
flyway -url=jdbc:postgresql://staging/appdb \
  -user=ci -password=$PW migrate

MySQL

flyway -url=jdbc:mysql://staging/appdb \
  -user=ci -password=$PW migrate

5. 本番に手動承認ゲートを追加する

テスト/ステージングは自動とし、本番の migrate には手動承認を必須とする。CI/CD に「承認ゲート」(手動承認) のステップを追加する。承認前に 'flyway info' または 'liquibase status' でどのマイグレーションが実行されるかを示す。問題が起きた場合にロールバックできるよう、本番に適用する前に必ず最新のバックアップを取る。

PostgreSQL

# what will run before approval?
flyway info
# liquibase equivalent:
liquibase status --verbose

6. 可逆性とロールバック戦略を定義する

Flyway Community には自動 undo がないため、前進のみ (forward-only) のマイグレーション原則を採用する: 誤りを取り消すのではなく、それを修正する新しいマイグレーションを書く。Liquibase の changeset では rollback ブロックを定義でき、'liquibase rollback' でロールバックできる。最も堅牢な戦略: 変更を小さく後方互換に保ち、リスクのある操作 (列の削除) の前にバックアップを取り、文書化したロールバック計画を用意する。

PostgreSQL

-- Liquibase rollback example (inside a changeset)
--changeset dev:2
CREATE TABLE orders (...);
--rollback DROP TABLE orders;
DBAtlas で開く →