flyway について
Flywayでデータベース変更を管理する開発者向けのリファレンススキルです。マイグレーションの命名規則や設定、SQL・Javaの例、トラブルシューティングを扱います。
主な機能
- 01バージョン・リピータブルマイグレーションの命名
- 02Spring Bootの設定例
- 03SQL・Javaマイグレーション例
- 04Mavenの実行・検証コマンド
- 05トラブルシューティングの案内
活用シーン
- 01データベーススキーマ変更の計画
- 02データマイグレーションスクリプトの作成
- 03検証やバージョンエラーの調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill flywayインストール後、Claude Code で/flywayを入力して読み込まれたか確認します。
詳細
Flyway データベースマイグレーション
深い知識:包括的なドキュメントについては、technology:
flywayを指定してmcp__documentation__fetch_docsを使用してください。
Maven の設定
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
</dependency>
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>${flyway.version}</version>
<configuration>
<url>jdbc:postgresql://localhost:5432/mydb</url>
<user>myuser</user>
<password>mypass</password>
</configuration>
</plugin>
アプリケーションの設定
spring:
flyway:
enabled: true
baseline-on-migrate: true
locations: classpath:db/migration
validate-on-migrate: true
out-of-order: false
clean-disabled: true # Prevent clean in production!
マイグレーションの命名規則
V{version}__{description}.sql # Versioned migrations
U{version}__{description}.sql # Undo migrations (Teams/Enterprise)
R__{description}.sql # Repeatable migrations
例:
V1__create_users_table.sqlV1.1__add_email_index.sqlV2__create_departments_table.sqlR__create_views.sql
初期スキーマのマイグレーション
-- V1__init_schema.sql
-- Users table
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role VARCHAR(20) NOT NULL DEFAULT 'USER',
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP,
created_by VARCHAR(255),
updated_by VARCHAR(255)
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_status ON users(status);
CREATE INDEX idx_users_role ON users(role);
-- Roles table
CREATE TABLE roles (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE,
description VARCHAR(255)
);
-- Insert default roles
INSERT INTO roles (name, description) VALUES
('ADMIN', 'System administrator'),
('MANAGER', 'Department manager'),
('USER', 'Regular user');
カラム追加のマイグレーション
-- V2__add_phone_to_users.sql
ALTER TABLE users
ADD COLUMN phone VARCHAR(20);
CREATE INDEX idx_users_phone ON users(phone);
外部キー追加のマイグレーション
-- V3__create_departments.sql
CREATE TABLE departments (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE,
code VARCHAR(10) NOT NULL UNIQUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE users
ADD COLUMN department_id BIGINT;
ALTER TABLE users
ADD CONSTRAINT fk_users_department
FOREIGN KEY (department_id) REFERENCES departments(id);
CREATE INDEX idx_users_department ON users(department_id);
データのマイグレーション
-- V4__migrate_legacy_data.sql
-- Update existing data
UPDATE users
SET role = 'USER'
WHERE role IS NULL;
-- Migrate data from legacy format
INSERT INTO departments (name, code)
SELECT DISTINCT department_name, UPPER(SUBSTRING(department_name, 1, 3))
FROM legacy_employees
WHERE department_name IS NOT NULL;
リピータブルマイグレーション(ビュー)
-- R__create_user_summary_view.sql
DROP VIEW IF EXISTS user_summary;
CREATE VIEW user_summary AS
SELECT
u.id,
u.name,
u.email,
u.role,
u.status,
d.name AS department_name,
u.created_at
FROM users u
LEFT JOIN departments d ON u.department_id = d.id;
Java ベースのマイグレーション
@Component
public class V5__ComplexDataMigration implements JavaMigration {
@Override
public void migrate(Context context) throws Exception {
try (Statement stmt = context.getConnection().createStatement()) {
// Complex migration logic
ResultSet rs = stmt.executeQuery("SELECT id, data FROM legacy_table");
while (rs.next()) {
// Process and migrate data
}
}
}
@Override
public Integer getChecksum() { return null; }
@Override
public MigrationVersion getVersion() {
return MigrationVersion.fromVersion("5");
}
@Override
public String getDescription() {
return "Complex data migration";
}
}
ログ記録用コールバック
@Component
public class FlywayCallback implements Callback {
private static final Logger log = LoggerFactory.getLogger(FlywayCallback.class);
@Override
public boolean supports(Event event, Context context) {
return event == Event.AFTER_EACH_MIGRATE ||
event == Event.AFTER_MIGRATE_ERROR;
}
@Override
public boolean canHandleInTransaction(Event event, Context context) {
return true;
}
@Override
public void handle(Event event, Context context) {
if (event == Event.AFTER_EACH_MIGRATE) {
MigrationInfo info = context.getMigrationInfo();
log.info("Migrated: {} - {} ({}ms)",
info.getVersion(),
info.getDescription(),
info.getExecutionTime());
} else if (event == Event.AFTER_MIGRATE_ERROR) {
log.error("Migration failed!");
}
}
@Override
public String getCallbackName() {
return "LoggingCallback";
}
}
Maven コマンド
# Run migrations
mvn flyway:migrate
# Show migration info
mvn flyway:info
# Validate migrations
mvn flyway:validate
# Repair checksum mismatches
mvn flyway:repair
# Clean database (careful!)
mvn flyway:clean
# Baseline existing database
mvn flyway:baseline
ベストプラクティス
| プラクティス | 説明 |
|---|---|
| 適用済みのマイグレーションは編集しない | 代わりに新しいマイグレーションを作成します |
| マイグレーションをテストする | テストでは H2 を使用します |
| マイグレーション前にバックアップする | 特に本番環境では重要です |
| トランザクションを使用する | DDL をトランザクションで囲みます |
| バージョン管理 | マイグレーションを Git で管理します |
| 命名規則 | 内容がわかる名前を付けます |
このスキルを使用しない場合
- 一般的なマイグレーション戦略 - 概念については
migrationsスキルを使用します - Liquibase - Liquibase 専用のドキュメントを使用します
- Prisma のマイグレーション -
prismaスキルを使用します - TypeORM のマイグレーション -
typeormスキルを使用します
アンチパターン
| アンチパターン | 問題 | 解決策 |
|---|---|---|
| 適用済みのマイグレーションを変更する | チェックサム検証に失敗します | 代わりに新しいマイグレーションを作成します |
| 既存の DB にベースラインがない | マイグレーションの実行に失敗します | baseline-on-migrate: true を使用します |
| SQL マイグレーションに複雑なロジックを含める | テストやデバッグが困難です | Java ベースのマイグレーションを使用します |
| 検証を無視する | 環境間に不整合が生じます | デプロイ前に必ず検証します |
| 本番環境で clean-disabled: false にする | データ損失のリスクがあります | 本番環境では必ず clean を無効にします |
| 順不同のマイグレーション | バージョンの競合が発生します | 連番でバージョンを付けます |
トラブルシューティング(クイックガイド)
| 問題 | 診断 | 対処法 |
|---|---|---|
| チェックサムの不一致 | ファイルと flyway_schema_history を比較します | flyway repair を実行するか、新しいマイグレーションを作成します |
| 順不同エラー | バージョン番号を確認します | バージョンを修正するか、out-of-order: true を設定します |
| マイグレーションの失敗 | flyway_schema_history.success を確認します | 修復して問題を解決し、再試行します |
| マイグレーションが見つからない | locations の設定を確認します | classpath:db/migration のパスを確認します |
| ベースラインの競合 | baseline-version を確認します | 正しいベースラインバージョンを設定します |
リファレンスドキュメント
コメント
Markdown 対応