- Spring
Flywayの使い方|Spring Boot・命名規則・失敗時の直し方
Flyway は、DB のテーブル変更を「番号付きの SQL ファイル」で管理し、まだ流していないものだけを順に実行するツールです。 Spring Boot では、src/main/resources/db/migration に V1__create_users.sql のようなファイルを置くと、アプリの起動時に自動で流れます。どこまで流したかは、DB の中の flyway_schema_history という表に記録されます。
Spring Boot 4 からは、flyway-core だけでは自動実行されません。spring-boot-starter-flyway を入れます。 PostgreSQL や MySQL では、DB ごとのモジュール(flyway-database-postgresql など)も要ります。
| よくあるエラー(原文の先頭) | 原因 | 直し方 |
|---|---|---|
Migration checksum mismatch for migration version 1 |
流し終えた SQL ファイルを書き換えた | 元に戻す。意図した変更なら repair |
Detected failed migration to version 3 |
前回の実行が途中で失敗し、失敗の記録が残っている | 途中まで変わった部分を手で戻し、repair してから流し直す |
Detected resolved migration not applied to database: 2.5. |
適用済みの版より小さい版のファイルを後から足した | 版番号を振り直す。どうしても要るなら outOfOrder=true |
Detected applied migration not resolved locally: 2.5. |
適用済みのファイルを消した | ファイルを戻す。意図して消したなら repair |
Found non-empty schema(s) "public" but no schema history table. |
既存の DB に初めて Flyway を入れた | baselineOnMigrate=true(Boot は spring.flyway.baseline-on-migrate) |
No Flyway database plugin found to handle jdbc:postgresql://… |
DB ごとのモジュールが無い | flyway-database-postgresql を足す |
確認環境:Spring Boot 4.1.1(GitHub のリリースで最新の安定版)が管理する Flyway 12.4.0 と、PostgreSQL 16.15・OpenJDK 21.0.10(Linux)。Flyway は GitHub のタグ flyway-12.4.0 のソースからビルドした Java API(Flyway.configure()…migrate())で動かし、この記事のエラー文とログはその出力です。Spring Boot 側の設定名・既定値は、タグ v4.1.1 のソースの FlywayProperties(設定クラス)と、Spring Boot のドキュメント・4.0 移行ガイドで確かめました。Flyway 単体の最新版は 13.10.0 です(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Flywayの使い方|Spring Boot・命名規則・失敗時の直し方」
Flyway のしくみ:3つの言葉
| 言葉 | 意味 |
|---|---|
| マイグレーション | DB の変更を書いた1つのファイル(V1__create_users.sql など)。一度流したら書き換えない |
スキーマ履歴表(flyway_schema_history) |
どのファイルを、いつ、成功したか、チェックサム(中身から計算した数値)は何か、を記録する表 |
| チェックサム | ファイルの中身から計算した値。流した後に中身が変わると、記録とずれてエラーになる |
migrate(流す)を呼ぶと、Flyway は次の順に動きます。
flyway_schema_historyが無ければ作るvalidate:適用済みのファイルが書き換えられていないか、チェックサムを比べる- まだ流していない版(Pending)を、版番号の小さい順に流す
- 中身が変わった繰り返し用(
R__)のファイルを流す - 1ファイルごとに、結果を
flyway_schema_historyに記録する
ファイル名の規則(早見表)
形は 接頭辞 + 版 + __(アンダースコア2つ)+ 説明 + .sql です。 Flyway のドキュメントでは「prefixVERSIONseparatorDESCRIPTIONsuffix」と書かれ、既定値では V1.1__My_description.sql になります。
| 接頭辞 | 種類 | 例 | いつ流れるか |
|---|---|---|---|
V |
版付き(Versioned) | V1__create_users.sql |
1回だけ。版の小さい順 |
R |
繰り返し(Repeatable) | R__users_view.sql |
中身が変わるたび。版付きの後に、説明の順 |
B |
ベースライン(Baseline) | B2__baseline.sql |
新しい DB でだけ。それ以下の版を飛ばす |
U |
取り消し(Undo) | U3__drop_orders.sql |
undo コマンドのとき。Flyway Teams(有料版)の機能 |
版と説明の書き方
| 書き方 | 結果(Flyway 12.4.0 の info) |
|---|---|
V1.1__b.sql と V1_2__c.sql |
版は 1.1・1.2。版の中の _ は . と同じ扱い |
V2__d.sql と V10__e.sql |
1 → 2 → 10 の順。文字列ではなく数値で並ぶ |
V2026.10.12.1__f.sql |
版は 2026.10.12.1。日付を版にする書き方もできる |
V01__dup.sql と V1__a.sql |
Found more than one migration with version 01。先頭の0は無視され、同じ版になる |
V3__dup.sql と V3__create_orders.sql |
Found more than one migration with version 3 で止まる |
V4_add_index.sql(_ が1つ) |
エラーにならず黙って無視された(下の囲み) |
v5__lower.sql(小文字の v) |
これも無視された |
説明の _ |
表示では空白になる(create_users → create users) |
区切りを _ 1つにすると、エラーにならずに無視されます。 ログには次の2行が出るだけでした。
INFO: 1 SQL migrations were detected but not run because they did not follow the filename convention.
INFO: Set 'validateMigrationNaming' to true to fail fast and see a list of the invalid file names.
validateMigrationNaming を true にすると、起動時に止まって、ファイル名を教えてくれます。
org.flywaydb.core.api.FlywayException: Invalid SQL filenames found:
Invalid versioned migration name format: V4_add_index.sql (could not recognise version number 4_add_index)
Spring Boot では spring.flyway.validate-migration-naming=true を入れておくと、名前の書き間違いに早く気づけます。
B(ベースライン)は、ビルドした Flyway 12.4.0(オープンソース版)で動きました。V1・V2・B2・V3 を置いた空の DB では、B2 と V3 だけが流れ、V1 は Below Baseline、V2 は Ignored (Baseline) になりました。U3__undo.sql は、上と同じ「名前の規則に合わないファイル」として数えられ、流れませんでした。
テーブル名やインデックス名の付け方は、関連記事「DB命名規則一覧|テーブル名・カラム名・インデックス名・制約名」で扱っています。
Spring Boot 4 での導入
Boot 4 で変わった依存
Spring Boot 4.0 の移行ガイドには、「Flyway や Liquibase は、以前は第三者の依存(flyway-core)だけを入れていた。spring-boot-starter-flyway に切り替える」という趣旨が書かれています。Boot 4 では自動設定が spring-boot-flyway というモジュールに分かれたため、starter(必要なものをまとめた依存)を入れないと、起動時に流れません。
| Boot 3 まで | Boot 4 | |
|---|---|---|
| Flyway 本体 | org.flywaydb:flyway-core |
org.springframework.boot:spring-boot-starter-flyway |
| PostgreSQL | flyway-database-postgresql |
同じ(flyway-database-postgresql) |
| MySQL | flyway-mysql |
同じ(flyway-mysql) |
| テスト用 | spring-boot-starter-test |
spring-boot-starter-flyway-test(spring-boot-starter-test も一緒に入る) |
| 管理される版(4.1.1) | — | Flyway 12.4.0 |
Boot のドキュメントでは、「インメモリやファイルの DB(H2 など)は starter だけで動く。それ以外は DB ごとのモジュールも要る」とあり、例として flyway-database-postgresql と flyway-mysql が挙がっています。
Boot 4 の starter の名前の変更は、関連記事「Spring Boot starter一覧|用途別の選び方とBoot 4の新旧対応表」で、移行の全体は、関連記事「Spring Boot 4移行の手順|3から4の変更点一覧とチェックリスト」で扱っています。
build.gradle.kts
plugins {
java
id("org.springframework.boot") version "4.1.1"
id("io.spring.dependency-management") version "1.1.7"
}
java { toolchain { languageVersion = JavaLanguageVersion.of(21) } }
repositories { mavenCentral() }
dependencies {
implementation("org.springframework.boot:spring-boot-starter-webmvc")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-flyway") // Boot 4 はこれ
implementation("org.flywaydb:flyway-database-postgresql") // PostgreSQL 用
runtimeOnly("org.postgresql:postgresql")
testImplementation("org.springframework.boot:spring-boot-starter-flyway-test")
testImplementation("org.springframework.boot:spring-boot-starter-data-jpa-test")
}
tasks.test { useJUnitPlatform() }
pom.xml(dependencies の部分)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.1</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-flyway</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
版は親(spring-boot-starter-parent)が決めるので、<version> は書きません。Gradle の書き方の対訳は、関連記事「build.gradle書き方|Groovy/Kotlin DSL対訳と依存設定一覧」で扱っています。
フォルダとファイル
src/main/resources/
├── application.yml
└── db/migration/
├── V1__create_users.sql
├── V2__add_email_to_users.sql
└── R__users_view.sql
-- V1__create_users.sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
-- V2__add_email_to_users.sql
ALTER TABLE users ADD COLUMN email VARCHAR(255);
-- R__users_view.sql(中身が変わるたびに流れる)
CREATE OR REPLACE VIEW v_users AS SELECT id, name FROM users;
application.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/app
username: app
password: ${DB_PASSWORD}
jpa:
hibernate:
ddl-auto: validate # テーブルは Flyway が作る。JPA は照合だけ
flyway:
enabled: true
locations: classpath:db/migration
validate-migration-naming: true # 名前の書き間違いで止める
ddl-auto は validate か none にします。 update のままだと、Hibernate(JPA)と Flyway の両方がテーブルを変えようとします。Boot のドキュメントでも、Flyway を使うときに schema.sql・data.sql を一緒に使うことはすすめられていません。
実行結果(初回)
3つのファイルを空の DB に流したときのログです。
INFO: Database: jdbc:postgresql://127.0.0.1:55439/demo (PostgreSQL 16.15)
INFO: Schema history table "public"."flyway_schema_history" does not exist yet
INFO: Successfully validated 3 migrations (execution time 00:00.047s)
INFO: Creating Schema History table "public"."flyway_schema_history" ...
INFO: Current version of schema "public": << Empty Schema >>
INFO: Migrating schema "public" to version "1 - create users"
INFO: Migrating schema "public" to version "2 - add email to users"
INFO: Migrating schema "public" with repeatable migration "users view"
INFO: Successfully applied 3 migrations to schema "public", now at version v2 (execution time 00:00.015s)
flyway_schema_history の中身です。
installed_rank | version | description | type | script | checksum | success
----------------+---------+--------------------+------+----------------------------+-------------+---------
1 | 1 | create users | SQL | V1__create_users.sql | -1198624226 | t
2 | 2 | add email to users | SQL | V2__add_email_to_users.sql | -789335033 | t
3 | | users view | SQL | R__users_view.sql | -2128053619 | t
R__users_view.sql の中身を変えて流すと、そのファイルだけがもう一度流れ、前の記録は Superseded(置き換え済み)になりました。
Repeatable users view SQL Superseded -2128053619
Repeatable users view SQL Success -1765499091
spring.flyway.* 設定一覧(Boot 4.1.1)
Spring Boot 4.1.1 のソースの FlywayProperties(@ConfigurationProperties("spring.flyway"))から、よく使うものを並べました。既定値はソースの初期値です。
基本
| 設定 | 既定値 | 意味 |
|---|---|---|
spring.flyway.enabled |
true |
Flyway を動かすか |
spring.flyway.locations |
classpath:db/migration |
SQL を探す場所。filesystem: も可。{vendor} で DB ごとに分けられる |
spring.flyway.fail-on-missing-locations |
false |
場所が無いとき止めるか |
spring.flyway.encoding |
UTF-8 |
SQL ファイルの文字コード |
spring.flyway.default-schema |
なし | Flyway が管理する既定のスキーマ |
spring.flyway.schemas |
なし | 管理するスキーマの一覧 |
spring.flyway.create-schemas |
true |
schemas のスキーマを作るか |
spring.flyway.table |
flyway_schema_history |
履歴表の名前 |
spring.flyway.target |
latest |
どの版まで流すか |
spring.flyway.url・user・password |
なし | Flyway 専用の接続。無ければ spring.datasource.* を使う |
検証・順序・ベースライン
| 設定 | 既定値 | 意味 |
|---|---|---|
spring.flyway.validate-on-migrate |
true |
流す前にチェックサムなどを確かめるか |
spring.flyway.validate-migration-naming |
false |
名前の規則に合わないファイルで止めるか |
spring.flyway.ignore-migration-patterns |
*:future |
検証で無視する状態(例:*:missing) |
spring.flyway.out-of-order |
false |
小さい版を後から流すのを許すか |
spring.flyway.baseline-on-migrate |
false |
履歴表の無い既存 DB で、自動で baseline するか |
spring.flyway.baseline-version |
1 |
baseline で付ける版 |
spring.flyway.baseline-description |
<< Flyway Baseline >> |
baseline の説明 |
spring.flyway.clean-disabled |
true |
clean(全部消す)を禁止するか |
ファイル名・プレースホルダー
| 設定 | 既定値 | 意味 |
|---|---|---|
spring.flyway.sql-migration-prefix |
V |
版付きの接頭辞 |
spring.flyway.repeatable-sql-migration-prefix |
R |
繰り返しの接頭辞 |
spring.flyway.sql-migration-separator |
__ |
区切り |
spring.flyway.sql-migration-suffixes |
.sql |
拡張子 |
spring.flyway.placeholders.* |
なし | SQL の中の ${名前} を置き換える値 |
spring.flyway.placeholder-replacement |
true |
置き換えをするか |
spring.flyway.placeholder-prefix・-suffix |
${・} |
プレースホルダーの囲み |
実行のしかた・接続
| 設定 | 既定値 | 意味 |
|---|---|---|
spring.flyway.execute-in-transaction |
true |
SQL をトランザクションの中で流すか |
spring.flyway.group |
false |
未適用の全ファイルを1つのトランザクションにまとめるか |
spring.flyway.mixed |
false |
1ファイルにトランザクション可・不可の文を混ぜるのを許すか |
spring.flyway.connect-retries |
0 |
DB に繋がらないときの再試行回数 |
spring.flyway.connect-retries-interval |
120(秒) |
再試行の最大の間隔 |
spring.flyway.lock-retry-count |
50 |
ロックを取る再試行回数 |
spring.flyway.init-sqls |
なし | 接続直後に流す SQL |
spring.flyway.installed-by |
なし | 履歴表に記録する実行ユーザー名 |
spring.flyway.postgresql.transactional-lock |
Flyway の既定(true) |
PostgreSQL のロックをトランザクション単位にするか |
この他に、callback-locations・skip-default-callbacks・loggers(既定 slf4j)などがあります。dry-run-output や oracle.sqlplus などは、ソースのコメントに「Requires Flyway Teams」とある有料版向けです。
Boot の設定ファイル全般は、関連記事「Spring Boot application.properties設定一覧」で、環境ごとの切り替えは、関連記事「Spring Bootプロファイル切り替え|application.ymlと優先順位」で扱っています。
失敗したときの直し方
ここからは、実際にエラーを起こして、原文と直し方を確かめた結果です。
① Migration checksum mismatch(流した後に書き換えた)
流し終えた V1__create_users.sql の VARCHAR(100) を VARCHAR(200) に書き換えて起動すると、次のエラーで止まりました。
org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation
Migration checksum mismatch for migration version 1
-> Applied to database : -1198624226
-> Resolved locally : -1443686297
Either revert the changes to the migration, or run repair to update the schema history.
Applied to database は履歴表に記録された値、Resolved locally は今のファイルから計算した値です。
| 状況 | 直し方 |
|---|---|
| 間違って書き換えた | ファイルを元に戻す(git で戻すのが確実) |
| コメントや空白だけを直した | repair で記録のチェックサムを今のファイルに合わせる |
| テーブルの形を変えたい | 元のファイルは戻し、新しい版(V3__…)で ALTER TABLE を書く |
repair を実行したときのログです。DB のテーブルは変わらず、履歴表のチェックサムだけが書き換わりました。
INFO: Repair of failed migration in Schema History table "public"."flyway_schema_history" not necessary. No failed migration detected.
INFO: Repairing Schema History table for version 1 (Description: create users, Type: SQL, Checksum: -1443686297) ...
INFO: Successfully repaired schema history table "public"."flyway_schema_history" (execution time 00:00.109s).
repair で合わせても、すでに作られたテーブルは VARCHAR(100) のままです。 書き換えた中身は、新しく作る DB にしか効きません。環境ごとに形がずれるので、形の変更は新しい版で書きます。カラムの追加や型の変更の SQL は、関連記事「ALTER TABLEでカラム追加・型変更|MySQL・PostgreSQL比較」で扱っています。
② SQL の誤りで失敗した(PostgreSQL では全部戻る)
V3__create_orders.sql の最後の行を ADD COLUM(N が抜けた)にして流しました。
SEVERE: Migration of schema "public" to version "3 - create orders" failed! Changes successfully rolled back.
org.flywaydb.core.internal.exception.FlywayMigrateException: Failed to execute script V3__create_orders.sql
----------------------------------------------
SQL State : 42601
Error Code : 0
Message : ERROR: syntax error at or near "TEXT"
Position: 35
Location : src/main/resources/db/migration/V3__create_orders.sql (…/V3__create_orders.sql)
Line : 6
Statement : Run Flyway with -X option to see the actual statement causing the problem
PostgreSQL は DDL(CREATE TABLE など)もトランザクションで戻せるので、1行目の CREATE TABLE orders も取り消され、orders 表は残っていませんでした。 履歴表にも記録されず、V3 は Pending(未適用)のままです。この場合は、ファイルを直してもう一度起動するだけで流れます。Line : 6 が、ファイルの中で失敗した行です。
③ Detected failed migration(失敗の記録が残った)
DDL をトランザクションで戻せない DB(MySQL など)や、トランザクションの外で流す文(PostgreSQL の CREATE INDEX CONCURRENTLY など)が途中で失敗すると、履歴表に success = false の行が残ります。 Flyway のソースでも、「DDL のトランザクションに対応していない、またはトランザクションの外で流した」ときに、失敗の行を書く作りになっていました。このときのログは「戻せた」ではなく、次の文になります。
SEVERE: Migration of schema "public" to version "3 - create orders" [non-transactional] failed! Please restore backups and roll back database and code!
この状態でもう一度起動すると、流す前の検証で止まります。
org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation
Detected failed migration to version 3 (create orders).
Please remove any half-completed changes then run repair to fix the schema history.
直す手順
- 失敗したファイルのうち、途中まで成功した部分を手で戻す(作りかけの表・インデックスを
DROPする) - SQL ファイルを直す
repairを実行する(失敗の行が消える)- もう一度
migrate(アプリを起動)
repair の結果は repairActions=[Removed failed migrations]、履歴表の V3 は Failed から Pending に戻り、次の migrate で Success になりました。Flyway のドキュメントにも、repair は「失敗した記録を消す。残ったオブジェクトは手で片付ける」とあります。
④ 小さい版を後から足した
V3 まで流した DB に、別のブランチで作った V2_5__add_phone_to_users.sql が後から入ってきた場合です。
org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation
Detected resolved migration not applied to database: 2.5.
To ignore this migration, set -ignoreMigrationPatterns='*:ignored'. To allow executing this migration, set -outOfOrder=true.
| 直し方 | やること | 向いている場面 |
|---|---|---|
| 版を振り直す(第一候補) | V2_5__… を V4__… に名前を変える |
まだどの環境にも流していない |
outOfOrder=true |
spring.flyway.out-of-order=true で、小さい版も流す |
環境ごとに流れた順が違ってもよいと判断した |
| 無視する | ignore-migration-patterns: "*:ignored" |
一時的に止めずに起動したい |
outOfOrder=true で流したときは、警告が出ました。
WARNING: outOfOrder mode is active. Migration of schema "public" may not be reproducible.
INFO: Migrating schema "public" to version "2.5 - add phone to users" [out of order]
info の状態は Out of Order になります。開発者が同時に版を作ると起きやすいので、版に日時を使う(V2026.10.12.1__…)チームもあります。 ブランチの運用は、関連記事「Gitのブランチ戦略|Git Flow・GitHub Flowの違いと選び方」で扱っています。
⑤ Detected applied migration not resolved locally(ファイルを消した)
適用済みの V2_5__… をフォルダから消して起動しました。
Detected applied migration not resolved locally: 2.5.
If you removed this migration intentionally, run repair to mark the migration as deleted.
ブランチの切り替えでファイルが無くなっただけなら、ファイルを戻します。意図して消したなら repair で「削除済み」の印を付けます。
⑥ No Flyway database plugin found(DB 用モジュールが無い)
PostgreSQL 用のモジュールを外して動かすと、接続の時点で止まりました。
org.flywaydb.core.api.FlywayException: No Flyway database plugin found to handle jdbc:postgresql://127.0.0.1:55439/demo. See https://help.red-gate.com/help/flyway-cli12/help_4.aspx?topic=reference/usage/database-troubleshooting for troubleshooting
flyway-database-postgresql(MySQL なら flyway-mysql)を依存に足します。
⑦ No migrations found(場所が違う)
classpath:db/migration に1つもファイルが無いと、エラーにならずに警告だけ出て起動が続きます。
WARNING: No migrations found. Are your locations set up correctly?
spring.flyway.fail-on-missing-locations=true にすると、Unable to resolve location classpath:db/migration. で止まりました。フォルダ名を db/migrations(s 付き)や db.migration にしていないかを確かめます。
PostgreSQL の CREATE INDEX CONCURRENTLY が止まる
PostgreSQL で CREATE INDEX CONCURRENTLY(表をロックせずにインデックスを作る文)を流すと、既定の設定では終わりませんでした。 30秒待っても進まず、pg_stat_activity を見ると次の状態でした。
state | wait_event_type | wait_event | query
---------------------+-----------------+------------+---------------------------------------------------
idle in transaction | Client | ClientRead | SELECT COUNT(*) FROM pg_namespace WHERE nspname=$1
active | Lock | virtualxid | CREATE INDEX CONCURRENTLY idx_users_name ON users ...
Flyway は既定で、ロックを「トランザクション単位」で取ります。そのトランザクションが開いたままなので、「他のトランザクションが終わるのを待つ」CONCURRENTLY が待ち続けた形です。Flyway のドキュメントにも「CREATE INDEX CONCURRENTLY のような文では false にする」とあります。
spring:
flyway:
postgresql:
transactional-lock: false
false(Flyway の設定名は flyway.postgresql.transactional.lock)にすると、[non-transactional] として流れ、すぐに終わりました。インデックスの種類は、関連記事「PostgreSQLインデックスの種類|B-tree/GIN/GiST/BRIN実測」で扱っています。
既存の DB に Flyway を入れる(baseline)
すでにテーブルがある DB に、そのまま Flyway を入れると、次のエラーで止まります。
org.flywaydb.core.api.FlywayException: Found non-empty schema(s) "public" but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table.
手順
- 今の本番の DB から、テーブル定義を
pg_dump --schema-onlyなどで取り出す - それを
V1__baseline.sqlとして置く(新しい環境を作るときに使う) - 次の変更から
V2__…で書く - 既存の DB では、初回だけ
baseline-on-migrate: trueで起動する
spring:
flyway:
baseline-on-migrate: true
baseline-version: 1 # 既定も 1。ここまでは「流したことにする」
実行すると、V1 は流されず、V2 だけが流れました。
INFO: Creating Schema History table "public"."flyway_schema_history" with baseline ...
INFO: Successfully baselined schema with version: 1
INFO: Current version of schema "public": 1
INFO: Migrating schema "public" to version "2 - add email to users"
INFO: Successfully applied 1 migration to schema "public", now at version v2 (execution time 00:00.003s)
Versioned 1 baseline users SQL Ignored (Baseline)
Versioned 1 << Flyway Baseline >> BASELINE Baseline
Versioned 2 add email to users SQL Success
baseline-on-migrate は、空でない DB に履歴表が無いときだけ働きます。 履歴表を作った後は何もしませんが、接続先を間違えたときに気づきにくくなるので、導入が終わったら false に戻す運用もあります。スキーマの取り出し方は、関連記事「pg_dump/pg_restoreの使い方|バックアップとリストアの実行例」で扱っています。
Spring Boot で repair を自動で呼ぶ(FlywayMigrationStrategy)
Boot は起動時に Flyway.migrate() を呼びます。この動きを変えたいときは、FlywayMigrationStrategy の Bean を作ります。次は「開発環境だけ、先に repair する」例です。
package com.example.demo.config;
import org.springframework.boot.flyway.autoconfigure.FlywayMigrationStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("dev")
public class DevFlywayConfig {
@Bean
FlywayMigrationStrategy repairThenMigrate() {
return flyway -> {
flyway.repair(); // チェックサムのずれ・失敗の記録を直す
flyway.migrate();
};
}
}
Boot 4 では、パッケージが org.springframework.boot.flyway.autoconfigure に変わっています(Boot 3 は org.springframework.boot.autoconfigure.flyway)。本番で毎回 repair すると、書き換えに気づけなくなるので、プロファイルで開発用に限っています。
Flyway の Java API を直接使う場合は、次の形です(この記事のエラー文は、この形で出したものです)。
Flyway flyway = Flyway.configure()
.dataSource("jdbc:postgresql://localhost:5432/app", "app", password)
.locations("classpath:db/migration")
.validateMigrationNaming(true)
.load();
MigrateResult result = flyway.migrate();
System.out.println(result.migrationsExecuted + " 件を適用、現在の版 " + result.targetSchemaVersion);
コマンドの一覧
| コマンド | 何をするか | Boot の起動時 |
|---|---|---|
migrate |
未適用のものを流す | 自動で呼ばれる |
info |
各ファイルの状態(Pending・Success・Failed など)を表示 | — |
validate |
適用済みのファイルとの差を確かめる | validate-on-migrate=true で migrate の前に呼ばれる |
repair |
失敗の記録を消し、チェックサムを合わせ、消えたファイルに印を付ける | — |
baseline |
既存 DB に履歴表を作り、指定の版までを「流したこと」にする | baseline-on-migrate=true で自動 |
clean |
スキーマの中を全部消す | 既定で禁止(clean-disabled=true) |
clean を禁止のまま呼ぶと、次のエラーになりました。
org.flywaydb.core.api.FlywayException: Unable to execute clean as it has been disabled with the 'flyway.cleanDisabled' property.
Maven・Gradle のプラグイン(mvn flyway:repair、gradle flywayRepair)や、コマンドライン版(flyway repair)でも、同じ名前のコマンドが使えます。Actuator を入れると、/actuator/flyway で適用済みの一覧を見られます。公開の設定は、関連記事「Spring Boot Actuator設定|エンドポイント一覧と公開設定の雛形」で扱っています。
本番運用のルール表
| ルール | 理由 | 設定・やり方 |
|---|---|---|
| 適用済みのファイルは書き換えない | チェックサムがずれて起動が止まる。環境ごとに形がずれる | 変更は新しい版で書く |
clean は禁止のまま |
本番のデータが全部消える | clean-disabled: true(既定) |
| ファイル名の規則を検証する | _ 1つや小文字の v は黙って無視される |
validate-migration-naming: true |
| 1ファイルには1つの目的 | 失敗したときに戻す範囲が分かりやすい | テーブル作成とデータ投入を分ける |
| 本番の前にバックアップ | トランザクションで戻せない変更がある | 流す前に取得する手順を決める |
repair は手で、理由を残して実行 |
書き換えや失敗を隠してしまう | 自動の repair は開発プロファイルだけ |
outOfOrder は原則 false |
環境ごとに流れた順が変わる | 版の振り方をチームで決める |
| 大きな表の変更は時間を見積もる | 起動時に流れるので、終わるまでアプリが起動しない | 検証環境で件数をそろえて計る |
| 本番の DB ユーザーと分ける | アプリの接続ユーザーに DDL 権限を持たせない | spring.flyway.user・password で別ユーザー |
| CI で空の DB に全部流す | 新しい環境で流れないファイルに早く気づく | テスト用の PostgreSQL で migrate |
CI で DB を立てて流す方法は、関連記事「CI/CDとは|GitHub Actionsで最初のパイプラインを作るまで」で、テストで本物の PostgreSQL を使う方法は、関連記事「Testcontainersの使い方|Spring BootでPostgreSQL」で扱っています。
よくある質問
Q. 取り消し(ロールバック)はどう書きますか。
A. U で始まる取り消しファイルは Flyway Teams(有料版)の機能で、オープンソース版の Flyway 12.4.0 では流れませんでした。オープンソース版では、取り消す内容を「新しい版」として書く(V5__drop_column_x.sql)形になります。
Q. テストのときだけ流したいデータがあります。
A. Boot のドキュメントでは、テスト用のファイルを src/test/resources 側に置く方法と、プロファイルごとに spring.flyway.locations を変える方法(例:classpath:/db/migration,classpath:/dev/db/migration)が紹介されています。
Q. Java でマイグレーションを書けますか。
A. 書けます。Boot のドキュメントでは、JavaMigration を実装した Bean が自動で Flyway に登録されるとあります。Flyway のチュートリアルでは、db/migration パッケージに V3__Anonymize のような名前のクラスを置き、BaseJavaMigration を継承しています。
Q. 起動時ではなく、デプロイの手順の中で流したいです。
A. spring.flyway.enabled=false でアプリの自動実行を止め、デプロイの手順で Maven・Gradle のプラグインやコマンドライン版の migrate を呼ぶ形があります。Flyway は流す前にロックを取る作りで(PostgreSQL ではアドバイザリロック)、ロックが取れないときの再試行回数は lock-retry-count(既定 50 回)で決まります。
Q. Liquibase とどちらがよいですか。
A. Flyway は SQL をそのまま書く形、Liquibase は XML・YAML などで変更を書く形が中心です。Boot はどちらにも対応していて、Boot 4 ではどちらも専用の starter(spring-boot-starter-flyway・spring-boot-starter-liquibase)を入れます。
まとめ
- ファイル名は
V版__説明.sql。区切りは__(2つ)。_1つや小文字のvは黙って無視される - Boot 4 は
spring-boot-starter-flyway+flyway-database-postgresqlなどの DB 用モジュール - checksum mismatch は書き換えが原因。元に戻すか、意図した変更なら
repair。形の変更は新しい版で - PostgreSQL の SQL エラーは全部戻るので、直して再起動。失敗の記録が残ったら、手で戻して
repair - 小さい版を後から足すと out of order。版を振り直すのが第一候補
- 既存 DB は
baseline-on-migrate。CREATE INDEX CONCURRENTLYはpostgresql.transactional-lock: false
参考・出典
確認日はいずれも 2026年10月13日です。
- Spring Boot ドキュメント「Database Initialization」(Execute Flyway Database Migrations on Startup):https://docs.spring.io/spring-boot/how-to/data-initialization.html
- Spring Boot 4.0 Migration Guide:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-4.0-Migration-Guide
- Spring Boot ソース(タグ v4.1.1、FlywayProperties ほか):https://github.com/spring-projects/spring-boot/tree/v4.1.1/module/spring-boot-flyway
- Flyway(GitHub、ソースとドキュメント・タグ flyway-12.4.0):https://github.com/flyway/flyway
- Redgate Flyway ドキュメント「Migrations」:https://documentation.red-gate.com/fd/migrations-271585107.html
- Redgate Flyway ドキュメント「SQL Migration Separator」:https://documentation.red-gate.com/fd/flyway-sql-migration-separator-setting-277579038.html
- Flyway ドキュメント「Repair」(GitHub、タグ flyway-12.4.0):https://github.com/flyway/flyway/blob/flyway-12.4.0/documentation/Reference/Commands/Repair.md
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Flywayの使い方|Spring Boot・命名規則・失敗時の直し方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。