テックブログ

Flyway入門:JavaでDBスキーマをバージョン管理する

Flyway入門:JavaでDBスキーマをバージョン管理する

Flywayは、データベースのスキーマ変更をマイグレーションファイルとして管理し、バージョン順に適用するためのDBマイグレーションツールです。V1__create_users.sqlV2__add_email_to_users.sqlのようなSQLファイルを用意すると、Flywayが未適用の変更を検出して順番に実行します。さらに、適用済みのマイグレーションはflyway_schema_historyという履歴テーブルで管理されるため、どの変更までDBへ反映されているかを確認できます。Java単体でも利用でき、Spring Bootでは依存関係を追加することでアプリケーション起動時にマイグレーションを実行する構成を作れます。

1. Flywayとは

1-1. DBマイグレーションを管理するツール

Flywayは、DBスキーマの変更手順をファイルとして管理し、その変更をデータベースへ適用するためのマイグレーションツールです。データベースそのものをGitのように保存するツールではなく、「DBを変更する手順」を管理します。

例えば、開発者が手作業でALTER TABLEを実行すると、誰がどの環境へ何を適用したのか分からなくなることがあります。Flywayでは、テーブル作成やカラム追加などの変更をSQLファイルとしてリポジトリへ保存し、同じ変更手順を開発環境・テスト環境・本番環境へ順番に適用できます。

Flyway導入前後の違いを簡単に整理すると、次のようになります。

【Flyway導入前】

開発者
  ↓
SQLを手動実行
  ↓
開発DB

別の開発者
  ↓
別途SQLを手動実行
  ↓
テストDB

→ どの変更がどこまで適用済みか把握しにくい
【Flyway導入後】

Git等で管理した
マイグレーションSQL
  ↓
Flyway
  ↓
未適用分を判定
  ↓
DBへ順番に適用
  ↓
flyway_schema_historyへ履歴記録

Flywayを使えばSQLそのものの安全性が自動的に保証されるわけではありません。危険なDROP TABLEや誤ったUPDATEを書けば、そのSQLが実行される可能性があります。Flywayは「変更手順と適用履歴を管理する仕組み」であり、SQLレビューやバックアップなどは別途必要です。

1-2. SQLファイルをバージョン順に適用する

Flywayの基本は、マイグレーションSQLへバージョンを付けて順番に適用することです。初学者は、まずV1V2V3と変更を積み上げるイメージを持つと理解しやすくなります。

例えば最初にユーザーテーブルを作るSQLをV1__create_users.sql、次にメールアドレス列を追加するSQLをV2__add_email_to_users.sqlとして保存します。Flywayはデータベースの履歴を確認し、V1まで適用済みならV2だけを実行します。

V1__create_users.sql
        ↓
V2__add_email_to_users.sql
        ↓
V3__...

この仕組みによって、「現在のDBがどんな状態か」だけでなく、「どの変更を積み重ねてその状態になったか」をコードと同じように履歴として管理できます。すでに適用済みのマイグレーションファイルは、気軽に書き換えず、新しい変更は新しいバージョンとして追加するのが基本です。

1-3. JavaやSpring Bootと組み合わせられる

FlywayはSpring Boot専用のツールではなく、Javaアプリケーション、コマンドライン、ビルドツールなどから利用できます。その中でもSpring BootはFlywayとの連携機能を持っているため、初学者でも導入しやすい組み合わせです。

Spring Bootプロジェクトでは、Flywayを依存関係へ追加し、DB接続情報とマイグレーションSQLを用意すると、アプリケーション起動時に未適用のマイグレーションを実行する構成を作れます。アプリケーションとDBスキーマの変更を同じリポジトリで管理しやすくなります。

本記事では、Spring BootとH2 Databaseを使います。H2はJavaで扱いやすい軽量なRDBMSで、学習用の最小構成を作りやすいためです。実務でPostgreSQLなどを使う場合でも、Flywayがマイグレーションファイルを検出して履歴を管理する基本的な考え方は同じです。

2. Flywayがマイグレーションを管理する仕組み

2-1. マイグレーションファイルを用意する

Flywayでは、DBへ適用したい変更をマイグレーションファイルとして用意します。SQLベースの基本的なマイグレーションでは、ファイル名にバージョンと説明を含めます。

例えば次の2ファイルを用意します。

V1__create_users.sql
V2__add_email_to_users.sql

V1V2がバージョンを表し、create_usersadd_email_to_usersが変更内容を表します。アンダースコアが2つある点にも注意してください。

最初のうちは複雑な命名規則を覚える必要はありません。「一度適用した変更はそのまま残し、次の変更は新しいバージョンとして追加する」という基本を優先して理解するとよいでしょう。

2-2. 未適用のファイルを検出する

Flywayは、用意されたマイグレーションファイルとDB側の適用履歴を比較し、まだ適用されていないファイルを検出します。すべてのSQLを起動のたびに最初から実行するわけではありません。

例えばDB側にV1の適用履歴があり、アプリケーション側にV1とV2が存在するとします。

マイグレーションファイル

V1__create_users.sql       ← 適用済み
V2__add_email_to_users.sql ← 未適用

この状態でFlywayがマイグレーションを実行すると、V1をもう一度実行するのではなく、未適用のV2を対象にします。

この判定に利用されるのがflyway_schema_historyです。Flywayは単に現在のテーブル構造を見て「たぶんV1は終わっている」と推測するのではなく、自分が管理している適用履歴をもとに判断します。

2-3. 適用結果を履歴として記録する

マイグレーションを実行すると、Flywayはその適用結果を履歴テーブルへ記録します。これにより、次回実行時にどこまで変更済みか判断できます。

代表的には、マイグレーションのバージョン、説明、スクリプト名、適用日時、実行時間、成功したかどうかなどの情報が管理されます。

イメージは次のとおりです。

flyway_schema_history

+---------+----------------------+------------------------+
| version | description          | script                 |
+---------+----------------------+------------------------+
| 1       | create users         | V1__create_users.sql   |
| 2       | add email to users   | V2__add_email_to_users.sql |
+---------+----------------------+------------------------+

実際のテーブルにはこれ以外の管理項目もあります。重要なのは、このテーブルがFlyway自身の適用履歴を管理するためのものであり、通常のアプリケーションデータを保存するテーブルではないことです。

3. Spring BootへFlywayを導入する

3-1. Flywayの依存関係を追加する

Spring BootでFlywayを使うには、まずFlywayの依存関係をプロジェクトへ追加します。本記事ではMavenを使い、Gradleの詳細は扱いません。

pom.xmlへ次の依存関係を追加します。

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

何を設定しているか: flyway-coreはFlyway本体、h2は今回利用するデータベースです。Spring BootのDependency Managementを利用している場合は、対応するライブラリバージョンをSpring Boot側で管理できる構成があります。

Spring BootやFlywayのバージョンによって、対応DBや追加モジュールの扱いが異なる場合があります。実際のプロジェクトでは、使用しているバージョンのSpring BootとFlyway公式ドキュメントも確認してください。

3-2. DB接続を設定する

次に、Spring Bootが接続するH2 Databaseを設定します。Flywayは通常、Spring Bootで設定されたDataSourceを利用してマイグレーションを実行します。

src/main/resources/application.propertiesへ、例えば次のように設定します。

spring.datasource.url=jdbc:h2:file:./data/sampledb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver

何を設定しているか: spring.datasource.urlでH2のDBファイルを指定し、ユーザー名とパスワード、JDBCドライバーを設定しています。今回はアプリケーションを再起動してもV1の適用履歴が残るよう、メモリDBではなくファイルDBを使っています。

Flyway専用の接続先を別途設定することもできますが、初学者向けの最小構成では、まずアプリケーションと同じDataSourceを使う流れを理解すれば十分です。

3-3. マイグレーションファイルを配置する

Spring BootとFlywayの標準的な構成では、SQLマイグレーションをclasspath:db/migrationへ配置します。Mavenプロジェクトなら、通常はsrc/main/resources/db/migrationです。

ディレクトリ構成は次のようになります。

src
└── main
    ├── java
    │   └── ...
    └── resources
        ├── application.properties
        └── db
            └── migration
                └── V1__create_users.sql

何を設定しているか: db/migrationをFlywayがマイグレーションを検索する場所として利用し、その中のV1__create_users.sqlをバージョン付きマイグレーションとして認識させます。

場所をカスタマイズすることもできますが、学習段階では標準的な配置を使うほうが分かりやすくなります。設定を増やす前に、標準構成で一度動作を確認するのがおすすめです。

4. 最初のマイグレーションを実行する

4-1. V1__create_users.sqlを作成する

最初のマイグレーションとして、usersテーブルを作成します。初期状態のDBへ必要なテーブルを作る処理をV1として記録します。

src/main/resources/db/migration/V1__create_users.sqlを作成します。

CREATE TABLE users (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);

何をしているか: usersテーブルを作成し、主キーのidとユーザー名を格納するnameカラムを定義しています。

このSQLが安全かどうかをFlywayが自動判断してくれるわけではありません。SQLの内容は開発者がレビューし、実際のDB製品に合ったSQLになっているか確認する必要があります。

4-2. アプリケーションを起動して適用する

Flywayを組み込んだSpring Bootアプリケーションを起動すると、起動処理の中でFlywayがマイグレーションを確認し、未適用の変更をDBへ反映する構成にできます。

基本的な流れは次のとおりです。

Spring Boot起動
      ↓
DataSourceを準備
      ↓
Flyway起動
      ↓
db/migrationを確認
      ↓
未適用マイグレーションを検出
      ↓
V1__create_users.sqlを実行
      ↓
usersテーブル作成
      ↓
flyway_schema_historyへ記録
      ↓
アプリケーション起動継続

何が重要か: DBにusersテーブルが存在するかだけでなく、「V1を適用してusersテーブルを作った」という履歴も残ります。

次回同じアプリケーションを起動したとき、V1がすでに成功済みならFlywayは通常、V1をもう一度新規マイグレーションとして適用しません。この仕組みにより、マイグレーションを積み上げていけます。

4-3. V2__add_email_to_users.sqlで変更を追加する

次に、既存のusersテーブルへemailカラムを追加します。V1を書き換えるのではなく、新しいV2マイグレーションを追加します。

src/main/resources/db/migration/V2__add_email_to_users.sqlを作成します。

ALTER TABLE users
ADD COLUMN email VARCHAR(255);

何をしているか: V1で作成済みのusersテーブルへ、新しいemailカラムを追加しています。

ディレクトリは次の状態になります。

db/migration
├── V1__create_users.sql
└── V2__add_email_to_users.sql

アプリケーションを再び起動すると、FlywayはV1が適用済み、V2が未適用であることを履歴から判断し、V2だけを適用します。

V1 → 適用済みなのでスキップ
V2 → 未適用なので実行

これがFlywayの基本的な使い方です。「今のusersテーブルを作るSQLを毎回完成形として書き換える」のではなく、「V1で作成し、V2でカラムを追加した」という変更履歴を残します。

5. Flywayの状態を確認する

5-1. migrateで未適用の変更を反映する

migrateは、まだDBへ適用されていないマイグレーションを実行するための操作です。Flywayで最も中心となる処理です。

Flywayは履歴テーブルとマイグレーションファイルを確認し、適用すべき変更をバージョン順に実行します。V1まで適用済みでV2が新しく追加されていれば、V2が対象になります。

Spring Bootではアプリケーション起動時にこのマイグレーション処理を自動実行する構成を利用できます。一方、Flyway CLIやMaven Plugin、Gradle Plugin、Java APIなどから明示的にmigrateを実行する方法もあります。

5-2. infoでマイグレーションの状態を確認する

infoは、マイグレーションが現在どのような状態なのか確認するための操作です。DBへ変更を適用することが目的ではなく、状況を把握するときに使います。

例えば、「V1とV2のどこまで適用済みか」「まだ実行されていないマイグレーションがあるか」といった状態を確認できます。開発中やデプロイ前に、DBとマイグレーションの状況を確認したい場面で役立ちます。

「SQLファイルを追加したはずなのに適用されない」といった問題を調査するときも、まず現在のマイグレーション状態を確認することで原因を絞り込みやすくなります。

5-3. validateで履歴とファイルの整合性を確認する

validateは、現在用意されているマイグレーションファイルと、すでにDBへ記録されている履歴の整合性を確認するための操作です。DBへ新しいスキーマ変更を適用する処理ではありません。

例えば、すでに適用済みのマイグレーションファイルが後から変更されているなど、履歴と手元のマイグレーションに不整合がある場合の検出に利用されます。

そのため、migrateinfovalidateは次のように役割を分けて理解するとよいでしょう。

操作主な役割いつ使うか
migrate未適用マイグレーションをDBへ適用するDBを新しいバージョンへ進めるとき
infoマイグレーションの現在状態を確認する適用済み・未適用を確認したいとき
validate履歴とマイグレーションファイルの整合性を確認するデプロイ前や不整合を確認したいとき

validateを実行しても、未適用のV2が自動的にDBへ反映されるわけではありません。変更を適用する役割はmigrateです。

6. flyway_schema_historyとは

6-1. 適用済みマイグレーションを記録する

flyway_schema_historyは、FlywayがどのマイグレーションをDBへ適用したかを管理するための履歴テーブルです。Flywayが未適用マイグレーションを判断するうえで重要な役割を持ちます。

初めてマイグレーションを実行すると、Flywayは必要に応じて履歴テーブルを用意し、成功したマイグレーションの情報を記録します。次回以降は、この履歴と手元のファイルを比較します。

例えばV1とV2まで適用されていれば、Flywayは「このDBはV2まで進んでいる」と判断できます。DBのテーブル構造だけを解析して推測しているわけではありません。

6-2. バージョンや適用結果を確認する

flyway_schema_historyには、マイグレーションの識別や適用状況を確認するための情報が保存されます。項目名や詳細はFlywayのバージョンなども確認する必要がありますが、代表的な考え方は共通しています。

主な情報としては、次のようなものがあります。

情報意味
versionマイグレーションのバージョン
descriptionマイグレーションの説明
script実行したファイル名
checksumマイグレーション内容の確認に利用する値
installed_on適用された日時
execution_time実行にかかった時間
success適用が成功したか

例えばV2__add_email_to_users.sqlが適用されていれば、V2に対応する行が履歴へ記録されます。Flywayはこの情報を利用して、次に何を実行すべきか判断します。

checksumなどを利用した詳細な不整合対応やrepairについては、Flywayを使い始める段階では深入りする必要はありません。まずは「適用済みファイルの内容を気軽に変更しない」という運用を身につけることが重要です。

6-3. 履歴を直接書き換えない

flyway_schema_historyはFlywayが管理するためのテーブルなので、通常のアプリケーションデータのように手作業で自由に更新することは避けます。履歴を書き換えると、Flywayの認識と実際のDB状態がずれる可能性があります。

例えば「V2をもう一度実行したい」という理由で履歴行だけを手動削除すると、実際にはemailカラムが存在しているのにFlywayはV2未適用だと判断し、再びALTER TABLEを実行しようとする可能性があります。

問題が発生した場合は履歴テーブルを直接編集して辻褄を合わせるのではなく、まず原因を確認し、Flywayが提供する正式な操作やチームの運用手順に従います。初学者のうちは特に、履歴テーブルを「確認する対象」と考えるのが安全です。

7. まとめ

7-1. Flyway導入からマイグレーション適用までの流れ

Flywayは、DBスキーマの変更をバージョン付きマイグレーションとして管理し、まだ適用されていない変更を順番にDBへ反映するツールです。DBの内容そのものをGitへ保存する仕組みではありません。

Spring Bootでは、Flywayの依存関係を追加し、DB接続を設定してdb/migrationへSQLを置くことで、起動時にマイグレーションを実行する構成を作れます。

今回の流れを整理すると、次のようになります。

1. Flywayを依存関係へ追加
        ↓
2. DataSourceを設定
        ↓
3. V1__create_users.sqlを作成
        ↓
4. Spring Bootを起動
        ↓
5. FlywayがV1を検出
        ↓
6. V1をDBへ適用
        ↓
7. flyway_schema_historyへ記録
        ↓
8. V2__add_email_to_users.sqlを追加
        ↓
9. 再度起動
        ↓
10. 未適用のV2だけを実行

この流れによって、「現在usersテーブルにemailがある」という状態だけでなく、「V1でusersを作り、V2でemailを追加した」という変更履歴まで管理できます。

7-2. Flywayを使い始めるときのチェックリスト

Flywayを導入するときは、複雑な機能を最初から覚えるより、バージョン付きSQLを追加して順番に適用する基本を確実に理解することが重要です。

特に、すでに適用したマイグレーションを後から書き換えるのではなく、新しい変更を新しいバージョンとして追加する習慣を持つと、チームで履歴を共有しやすくなります。

実装時には、次の項目を確認してください。

  • FlywayがDBマイグレーション管理ツールであることを理解している
  • DBそのものをGitへ保存する仕組みだと誤解していない
  • Spring BootへFlywayの依存関係を追加している
  • 利用するDBへの接続設定ができている
  • db/migrationへマイグレーションSQLを配置している
  • V1__create_users.sqlのようにバージョン付きファイルを作っている
  • DB変更を新しいバージョンとして追加している
  • 適用済みマイグレーションを気軽に書き換えていない
  • migrateが未適用変更を反映する処理だと理解している
  • infoが状態確認のための操作だと理解している
  • validateが整合性確認のための操作だと理解している
  • validate自体が未適用SQLを反映する処理ではないと理解している
  • flyway_schema_historyの役割を理解している
  • 履歴テーブルを手作業で自由に編集していない
  • SQLそのものの安全性は別途レビューしている
  • 使用中のSpring Boot・Flyway・DBの対応バージョンを公式資料で確認している

Flywayを使ううえで最も重要なのは、DBを「完成した現在状態」だけで見るのではなく、「V1、V2、V3と変更を積み重ねて現在状態になったもの」として扱うことです。この考え方を身につけると、JavaアプリケーションとDBスキーマの変更を同じ開発フローの中で管理しやすくなります。

8. 参考リンク

この記事では、次の公式資料を基準にしています。