MSA・DDD環境におけるFlyway・Liquibase・Bytebase・Atlasを比較し、状況に応じてどれを選ぶべきか整理しました。
1. スキーマは止まらずに変わる
DDDとMSA、クラウドネイティブ環境では、DBスキーマは固定資産ではありません。サービスを運用している間、絶えず変化し続けます。
理由はドメインにあります。エンティティとアグリゲートは、ドメインへの理解が深まるほど、ともに変化します。属性が追加され、ひとまとまりだった概念が二つに分かれ、カラムだった値が独立したテーブルへ昇格します。モデルが進化すれば、スキーマも進化します。
これをツールなしで手作業で ALTERだけ実行すると、環境ごとにスキーマが食い違います。マイグレーションツールは変更をバージョンで管理し、どの環境でも同じ順序で同じ状態に到達できるよう保証します。
MSAでは、ここに分散が加わります。サービスごとに独自のDBを持つ Database per Serviceでは、マイグレーションもサービス単位で行われます。中央からDDLを一度に適用するのではなく、複数のサービスがそれぞれの速度でスキーマを変更する状況を制御しなければなりません。無停止デプロイまで求められると、「テーブルをロックしてしばらく停止してから変更する」という方法は選択肢から外れます。
ツールを選ぶ前に:二つのアプローチ
|
方式 |
説明 |
代表的なツール |
|---|---|---|
|
変更(Migration)ベース |
スキーマを変更する手順を V1、 V2、 V3として積み重ねます。変更の累積が、そのまま現在の状態になります。 |
Flyway、Liquibase |
|
状態(宣言型)ベース |
目標スキーマを宣言すると、ツールが現在との差分を計算してスクリプトを生成します。 |
Atlas |
変更ベースは 意図が明示的で追跡しやすく、宣言型は 構成管理がすっきりして自動化に適しています。この違いが、ツール選びの出発点です。
2. 四つのツールを一目で比較
Flyway — 最もシンプルで、最も多く使われている
V1__create_member.sqlのように、バージョンと説明を付けたSQLファイルを順番に適用します。作成したSQLがそのまま実行されるため、何が実行されるか予測しやすく、Spring Bootとの統合もスムーズなので、起動時に自動適用するパターンがよく使われます。ただし、自動ロールバックやスキーマdiffは有料領域です。
-- V2__add_email_to_member.sql
ALTER TABLE member
ADD COLUMN email VARCHAR(255) NOT NULL DEFAULT '';
CREATE INDEX idx_member_email ON member (email);
作成したSQLがそのまま適用され、 flyway migrate を一度実行すれば完了です。
Liquibase — 抽象化とロールバック、規制対応の証跡
XML・YAML・JSON・SQLの changelogで変更を記述します。DBの種類に縛られない抽象化により、 複数のDBMSを同時にサポートしたり、 ロールバックを明示的に管理したりする場合に有利です。有料版(Liquibase Secure)では、ポリシーチェックや変更・ロールバックの監査証跡をSOX・PCI DSS・DORAなどの規制にマッピングできるため、規制が厳しい環境でよく選ばれます。
# db/changelog/002-add-email.yaml
databaseChangeLog:
- changeSet:
id: 002-add-email
author: dev
changes:
- addColumn:
tableName: member
columns:
- column: { name: email, type: varchar(255) }
rollback:
- dropColumn:
tableName: member
columnName: email
rollbackブロックを明示すると、liquibase rollbackによってそのまま元に戻せます。上記のように単純な変更であれば省略しても逆操作を自動生成します。表現力に優れている分、SQLを直接記述するFlywayよりも習得のハードルはやや高くなります。
|
規制略語の整理 - SOX(Sarbanes–Oxley Act)— 米国上場企業の会計・内部統制規制。財務データの変更に対する統制と証跡を求める。 - PCI DSS — カード決済データのセキュリティ基準。変更管理と監査ログを求める。 - DORA(Digital Operational Resilience Act)— EU金融機関の業務レジリエンス規制。変更履歴とロールバック能力の実証を求める。 |
|---|
Bytebase — DB DevOpsプラットフォーム
前の二つがライブラリ・CLIだとすれば、Bytebaseはプラットフォームです。Web GUI上で変更リクエスト → レビュー → 承認 → 適用のフローを運用し、SQLレビュー規則・変更履歴・アクセス制御を一元管理します。複数のチームが多数のDBを運用し、ガバナンスと監査証跡が重要な組織に適しています。一方で、導入の負担は大きくなります。
Atlas — 宣言型 + GitOps
望ましいスキーマをHCL・SQL・ORMで記述しておくと、現在の状態との差分を自動計算してマイグレーションを作成します。スキーマをコードとして宣言し、Gitで管理するGitOpsとの親和性が強みです。宣言型に慣れていない場合は、考え方を切り替える必要があります。
# schema.hcl — "최종 상태"를 선언한다
table "member" {
schema = schema.public
column "id" { type = bigint }
column "email" { type = varchar(255) }
primary_key { columns = [column.id] }
}
emailカラムを宣言に追加してatlas schema applyを実行すると、Atlasが現在のDBと比較してADD COLUMNを計算し、適用します。
比較表
|
項目 |
Flyway |
Liquibase |
Bytebase |
Atlas |
|---|---|---|---|---|
|
アプローチ |
変更ベース |
変更ベース |
変更ベース + プラットフォーム |
宣言型中心 |
|
記述形式 |
SQL |
XML/YAML/JSON/SQL |
SQL(+GUI) |
HCL/SQL/ORM |
|
対応DBMS |
30+ |
60+(クロスDB) |
25種類のエンジン |
主要オープンソースRDBMS |
|
ロールバック |
手動(自動化は商用) |
多数を自動化・raw SQLは明示 |
対応 |
計画・復元 |
|
自動diff |
なし |
一部 |
一部 |
強み |
|
レビュー・承認 |
外部CI |
外部CI |
内蔵(GUI) |
CI連携 |
|
監査証跡 |
限定的 |
SecureにおけるSOX/PCI/DORA |
変更・承認ログ |
変更計画・履歴 |
|
ライセンス |
OSS + 商用 |
OSS + Pro・Secure |
OSS + Enterprise |
OSS + Pro |
|
適している状況 |
シンプル・SQLフレンドリー |
マルチDB・ロールバック・規制 |
チームガバナンス |
宣言型・GitOps |
移植性もDBMSの数と同じくらい重要です。PostgreSQL・MySQL・Oracle・MS-SQLでは、同じ変更であってもDDL構文が異なりますが、Flywayはraw SQLを使用するため、製品ごとの差異を直接処理する必要があります。Liquibaseは抽象化されたchangelogから対象DBMSに合わせたSQLを生成するため、1つの定義で複数の製品群を同時にサポートしやすいです。顧客ごとにDBMSが異なる場合、この違いが選択を左右します。
3. どのように使うか - Flywayで見る動作とGitOps
マイグレーションファイルは、命名規則さえ守ればよいものです。
db/migration/
├── V1__create_member.sql
├── V2__add_email_to_member.sql
└── V3__create_post.sql
V{バージョン}__{説明}.sqlという形式で、バージョン順に一度だけ適用されます。よく使うコマンドは4つです。
• migrate — まだ適用されていないマイグレーションを順番に実行
• info — 適用履歴と保留中の変更を表示
• validate — 適用済みファイルが改ざんされていないか、チェックサムで検証
• baseline — 稼働中のDBに初めて導入する際に基準点を設定
validateは、思った以上に頻繁に事故を防ぎます。すでに適用されたファイルを誰かが後から変更すると、チェックサムの不一致によってマイグレーションが停止します。原則は1つです。適用済みのマイグレーションは変更せず、新しいバージョンを追加します。
マイグレーションはどのモジュールに置くのか
1つのサービスをドメイン・ブートなど複数のGradleモジュールに分割している場合、マイグレーションは実際のDBに接続して起動するブート(アプリケーション)モジュールに置きます。
member-service/
├── member-domain/ ← 엔티티·도메인 로직
└── member-boot/ ← 애플리케이션 부트·설정
└── src/main/resources/db/migration/ ← Flyway 마이그레이션
サービスが複数あり、リポジトリが分離されている場合は、各サービスが自身のリポジトリで同じパターンに従い、各ブートモジュールが自身のDBのマイグレーションを所有します(Database per Service)。
現実的なCI/CDパイプライン
クラウドネイティブでは、Gitを単一の信頼できる情報源(SSOT)として置くGitOpsが標準です。「PRを上げればCDが適用する」と要約されますが、エンタープライズの実際のフローはより緻密です。
• バージョン管理+レビュー — テーブル・インデックス・シードデータまで、すべての変更をコードと同じようにPRとして提出し、レビューします
• 自動検証 — CIで一時DBに適用して構文・制約・インデックスを確認し、危険なコマンド(条件のない DROP など)を静的検査でブロックします。実行アカウントには最小限の権限を付与します
• 下位環境での再現テスト — ステージングに適用した後、単体・統合・回帰・性能テストを実施します。特に、旧バージョンのコード+新バージョンのスキーマの後方互換性を確認します
• 承認ゲート — 本番反映前にMR承認またはITSMチケット承認を行います。リスク(低・中・高)に応じて段階が異なり、チケット番号を記録します
• バックアップの確保 — 本番適用の直前にバックアップを取得し、バックアップも定期的にリストアテストを行います
• 段階的な適用 — 冪等(idempotent)スクリプトでマイグレーションを先に適用し、それに依存するコードをデプロイします。Expand–Contractと組み合わせれば、順序依存性がなくなります
• モニタリング+機能フラグ — 適用直後から応答時間・コネクション・エラー率を監視します。機能フラグによって新機能をスキーマから分離します
• ロールバック検証 — 下位環境であらかじめ検証されたロールバック経路のみを使用します
ここで欠かせない原則が権限分離です。開発者は下位環境で自律的に作業しますが、本番反映はDBA・セキュリティの監督下で行います。また、最近のガイドでは、状態ベースのdiffよりも明示的なversionedマイグレーションが推奨されています。変更の予測可能性が高く、監査・再現が容易だからです。
ロールバックは「元に戻す」だけでは終わらない
規制環境では、元に戻したという事実と内容が証跡として残っているかまでが求められます。
• Flyway — undoではU1__...sqlのような逆方向のスクリプトを自分で作成する必要があり、自動undoは商用機能です。ロールバックも「もう一つのマイグレーション」であり、検証・記録の対象です。
• Liquibase — changelogの変更の多くではロールバックを自動生成し、raw SQLには明示的なrollbackブロックを記述します。Secureでは実行SQLを別テーブルに格納し、ロールバックレポート(誰が・いつ・何を・どのように)を出力します。
核心は、監査対象のシステムでは、ロールバックをその場で手作業で作成して本番環境で直接実行してはならないということです。事前に検証され、履歴が残る経路のみを通じて実行する必要があります。
生成と適用を分離するモデル
CDの自動適用の対極にあるのが、ツールはSQLだけを生成し、適用はDBAが変更ウィンドウに直接実行するこのようなモデルがあります。運用DBへのアクセスを一部の人にしか与えない金融・公共分野でよく見られます。
3つのツールはいずれも「適用せずにSQLだけを取り出す」コマンドを提供しています。
• Flyway — flyway migrate -dryRunOutput=deploy.sql
• Liquibase — liquibase update-sql(適用)、liquibase rollback-sql(ロールバック)
• Atlas — atlas migrate diff <name>でversioned SQLを生成
メリットは明確です。人がSQLを直接確認するため、統制・監査・権限分離が自然に行え、危険な変更を管理された時間帯に実行できます。
一方で、コストもあります。自動デプロイが途切れるためリードタイムが長くなり、テナントが増えると手作業がボトルネックになります。最大の落とし穴はドリフトです。DBAが生成されたスクリプトを本番環境で手作業で修正して実行すると、GitのSSOTと実際の適用内容にずれが生じます。原則は、生成されたスクリプトは修正せずそのまま実行し、修正が必要ならソースを修正して再生成することです。
そのため、最近の折衷案は、「DBAがレビュー・承認し、パイプラインが変更ウィンドウに適用する」というゲートモデルです。人による統制を維持しつつ、実行は自動化して証跡と再現性を両立させます。BytebaseとLiquibase Secureはこのモデルによく適合します。
4. 実践 — 無停止と大規模データ
ツールの使い方より難しいのは、稼働中のシステムを停止せずにスキーマを変更することです。
Expand–Contractパターン
無停止運用の基本です。変更を一度に行わず、3段階に分けます。
• 拡張(Expand) — 新しいカラム・テーブルを追加。既存コードへの影響はなし
• 移行(Migrate & Dual-write) — 新旧の両方に書き込むようにデプロイし、既存データをバックフィル
• 縮小(Contract) — トラフィックがすべて新しい構造を使用していることを確認した後、古いカラム・テーブルを削除
このようにすれば、デプロイ中のどの時点でもアプリケーションとスキーマが相互互換になります。カラム名の変更のように単純に見える作業でも、ローリングデプロイ中は旧バージョンのインスタンスが古いカラムを参照するため、1回のRENAMEでは無停止運用が破綻します。「追加 → 両方に書き込み → 削除」という手順で解決する必要があります。
元に戻せない変更
カラムの削除、型の変更、NOT NULLの追加は、一度に行うと危険です。常に、後方互換性を1段階残す方向に分解します。NOT NULLは、(1) カラム追加 → (2) 既存行のバックフィル → (3) 制約追加の順に分けます。
データ量が多い場合
テーブルに数千万行が蓄積すると、普通のALTER TABLE 1行だけで障害につながります。多くのDBでは、スキーマ変更がテーブルにロック(lock)をかけ、その間は読み取り・書き込みがブロックされるためです。小さなテーブルでは一瞬で終わるインデックス追加も、大きなテーブルでは数十秒間ロックを保持し、APIの遅延やコネクションプールの飽和に発展します。
大規模データでは、次の手法を使います。
• オンラインスキーマ変更 — MySQL系ならgh-ost、pt-online-schema-change。元のテーブルの代わりにシャドーテーブルを作成してデータを少しずつコピーし、変更分を同期した後、最後に瞬時に切り替えます。
• バッチバックフィル — 数億行を一度にUPDATEするとトランザクションが肥大化し、レプリケーション遅延が発生します。数千~数万行ずつに分け、負荷を見ながら埋めていきます。
• 大容量インデックス — PostgreSQLのCREATE INDEX CONCURRENTLYのように、書き込みをブロックしないオプションを活用します。トランザクション外で実行する必要があるため、マイグレーションツールのトランザクション分離オプションも併せて設定します。
原則は一つです。 大きなテーブルの変更は一度に行うのではなく、細かく分けて段階的に進めること。
国内事例2つ
① Flywayの導入 — JPAのddl-autoに依存していたチームが、ローカル・テスト・本番のスキーマが食い違う問題や、「本番環境でテーブルをDROPするのは危険だ」という現実に直面し、Flywayを導入しました。本番環境ではddl-auto: validateを設定し、エンティティとスキーマの不一致がある場合は起動自体を阻止し、変更はversionedスクリプトでのみ反映します。flyway_schema_historyのチェックサムで改ざんを検知し、適用済みのスクリプトは修正せず、新しいバージョンを追加することを運用ルールとして定着させました。先ほど見たvalidate・チェックサムの原則が、そのまま根付いた例です。 (Flyway適用記)
② 無停止での大容量移行 — 「いいね」機能をPostgreSQL → MySQLへ移行する際にスキーマまで変更することになり、データ量が多かったため移行に長い時間が必要でした。停止が不可能だったため、二重書き込みを採用しました。正本は従来のV1とし、V1の変更をSQS(FIFO)でV2へ流して、順序と整合性を維持しました。初期データはスクリプトで移行し、その間の変更分はSQSに蓄積しておき、V2のデプロイ後に消費して追いつかせました。参照はV1・V2を同時に提供しながら、段階的にV2へ移行するストラングラーパターンを採用し、SQSの購読処理を冪等に実装して、最後のイベントが最終状態になることを保証しました。著者が挙げた核心は、「マイグレーション中も更新され続けるデータをどのように同期するか」でした。 (マイグレーション後記)
5. では何を選ぶべきか
同じツールでも、どこで使うかによって答えは変わります。
インストール型SaaSプラットフォーム → Flyway
もしSaaSプラットフォームが独立したアプリ配布システムを通じて、購読 → インストール → 解約 → クリーンアップまでを自動的に処理するとしたら、どうなるでしょうか。
このライフサイクルが求めるものは2つあります。
• インストール時のスキーマ自動生成、購読キャンセル時の自動クリーンアップ — 人手を介さず、アプリ単位でスキーマが作成・削除されなければなりません。マイグレーションがアプリに組み込まれ、コードとともにデプロイされるモデルが適しています。
• モジュールごとの独立性 — モジュールごとにマイグレーションが分離され、それぞれが独自のバージョン履歴を持ちます。
|
⚠️ 購読キャンセル時のクリーンアップでマイグレーション履歴テーブルまで空にできないと、再インストール時に「適用済みのバージョン」と誤認され、初期スキーマが作成されない可能性があります。 |
|---|
この条件にはFlywayがよく適しています。アプリ起動時の自動適用がスムーズで、モジュールごとのSQLマイグレーションをアプリケーション構造にそのまま組み込めるうえ、インストール・クリーンアップのパイプラインにもシンプルに統合できます。構成管理と自動化をさらに一段階高めるなら、Atlas + GitOpsの組み合わせも選択肢です。
サイトプロジェクトなら → 業種別に
|
業種 |
要件 |
おすすめ |
|---|---|---|
|
金融・銀行業界 |
レビュー・承認監査+ロールバック証跡が必須。最も厳格。 |
Liquibase(Secure) — ポリシーチェックにより規定外の変更をブロックし、SOX・PCI・DORAにマッピング。承認をGUIで強制するなら Bytebaseを承認レイヤーとして追加 |
|
医療 |
個人情報・規制遵守、データ整合性・履歴追跡。 |
Liquibase — 明示的なchangelogとロールバック管理。承認ガバナンスがさらに必要なら Bytebaseで補完 |
|
社内イントラネット |
規制負担が低く、運用人員も限られている。シンプルさを優先。 |
Flyway — 軽量なSQL運用 |
まとめると、顧客企業では 安定性と監査証跡(ロールバックを含む)をどれだけ強く要求するかに比例して、Flyway → Liquibase → Bytebaseの方向へ重点が移ります。
クイックチェックリスト
• マイグレーションが アプリとともにデプロイされる必要があるか? → Flyway
• 複数のDBMS、明示的な ロールバック、 規制上の証跡(SOX・PCI・DORA)が重要か? → Liquibase(Secure)
• レビュー・承認ワークフローをGUIで強制する必要があるか? → Bytebase
• 宣言型の構成管理とGitOps自動化を目指しているか? → Atlas
6. おわりに
ツール選定で最も重要なのはツール自体ではなく、それを取り巻く ワークフローです。モデルが進化する限りスキーマも進化します。その変化を追跡可能かつ安全に、そして元に戻せるようにする手順が整っていれば、どのツールを使っても半分は解決したも同然です。
自動化されたライフサイクルを備えたプラットフォームには、シンプルで組み込みやすいツールを、金融・医療のように監査と統制が重要な顧客には、ガバナンスの強いツールを、状況に応じて選ぶとよいでしょう。導入を検討するなら、 変更が最も頻繁なサービスを1つ選び、小さなパイプラインから 始めるほうが安全です。
dnine