データベースマイグレーションツール完全チートシート

## 1. 基本概念

### マイグレーションとは
- **定義**: データベーススキーマの変更を管理・追跡する手法
- **目的**: 環境間の一貫性、変更履歴の管理、自動化
- **主な対象**: テーブル、カラム、インデックス、制約、初期データ

### 主要なマイグレーションツール比較
| ツール | 言語/プラットフォーム | 特徴 |
|--------|----------------------|------|
| Flyway | Java/多言語対応 | シンプルなSQL中心、学習コスト低 |
| Liquibase | Java/多言語対応 | XML/YAML/JSON/SQL対応、より詳細な制御 |
| Alembic | Python | SQLAlchemyと連携、Pythonプロジェクト向け |
| Prisma Migrate | Node.js | Prisma ORMと連携 |
| Rails Migrations | Ruby | Ruby on Rails組み込み |

## 2. プロジェクト初期設定 (Flyway例)

### インストール
```bash
# MacOS
brew install flyway

# Windows (Chocolatey)
choco install flyway

# Docker
docker pull flyway/flyway
```

### 設定ファイル (flyway.conf)
```properties
# 基本接続設定
flyway.url=jdbc:postgresql://localhost:5432/myapp
flyway.user=postgres
flyway.password=password

# 詳細設定
flyway.locations=filesystem:sql/migrations
flyway.schemas=public
flyway.baselineOnMigrate=true
flyway.outOfOrder=false
```

### フォルダ構造
```
プロジェクト/
├── flyway.conf
└── sql/
    └── migrations/
        ├── V1__Create_users_table.sql
        ├── V2__Add_email_column.sql
        └── V3__Create_products_table.sql
```

## 3. マイグレーションファイル命名規則

### 基本形式
```
V{バージョン}__{説明}.sql
```

### バージョニング戦略
1. **単純連番方式**:
   ```
   V1__Create_tables.sql
   V2__Add_indexes.sql
   ```

2. **セマンティックバージョニング**:
   ```
   V1_0_0__Initial_schema.sql
   V1_0_1__Bug_fix.sql
   V1_1_0__New_feature.sql
   ```

3. **タイムスタンプ方式** (推奨・チーム開発向け):
   ```
   V20240313120000__Create_users.sql
   V20240313125130__Add_user_indexes.sql
   ```

### 特殊マイグレーションタイプ
- **リピータブルマイグレーション**:
  ```
  R__Create_views.sql  # バージョン番号なし、何度でも実行可能
  ```

- **Undo マイグレーション** (Flyway Pro/Enterprise):
  ```
  U1__Undo_create_users.sql
  ```

## 4. 基本的なマイグレーション操作

### 初期化とベースライン
```bash
# 新規プロジェクト初期化
flyway baseline

# 既存DBをベースラインとして設定
flyway baseline -baselineVersion=1
```

### マイグレーション実行
```bash
# すべての未適用マイグレーションを実行
flyway migrate

# 特定バージョンまで実行
flyway -target=2 migrate
```

### 情報確認
```bash
# 現在の状態確認
flyway info

# 詳細表示
flyway info -verbose
```

### リセットと再実行
```bash
# DBをクリーンアップ (開発環境のみ！)
flyway clean

# クリーン後に再マイグレーション
flyway clean migrate
```

## 5. 一般的なマイグレーションパターン

### テーブル作成
```sql
-- V1__Create_users_table.sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(100) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_users_username ON users(username);
```

### テーブル変更
```sql
-- V2__Add_user_columns.sql
ALTER TABLE users ADD COLUMN email VARCHAR(100);
ALTER TABLE users ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'active';
```

### 初期データ投入
```sql
-- V3__Insert_initial_data.sql
INSERT INTO users (username, email) VALUES
('admin', 'admin@example.com'),
('system', 'system@example.com');
```

### ビュー作成 (リピータブル)
```sql
-- R__Create_admin_users_view.sql
CREATE OR REPLACE VIEW admin_users AS
SELECT * FROM users WHERE username = 'admin';
```

## 6. DBMS別の特記事項

### MySQL
- スキーマ = データベース
- 設定例:
  ```properties
  flyway.url=jdbc:mysql://localhost:3306/myapp
  flyway.user=root
  flyway.password=password
  ```

### PostgreSQL
- データベース > スキーマ > テーブル (階層構造)
- デフォルトスキーマは `public`
- 設定例:
  ```properties
  flyway.url=jdbc:postgresql://localhost:5432/myapp
  flyway.user=postgres
  flyway.password=password
  flyway.schemas=public,custom_schema
  ```

### Oracle
- ユーザー = スキーマ (1:1関係)
- 設定例:
  ```properties
  flyway.url=jdbc:oracle:thin:@localhost:1521:XE
  flyway.user=app_user  # これがスキーマ名になる
  flyway.password=password
  ```

### SQL Server
- サーバー > データベース > スキーマ > テーブル
- デフォルトスキーマは `dbo`
- 設定例:
  ```properties
  flyway.url=jdbc:sqlserver://localhost:1433;databaseName=myapp
  flyway.user=sa
  flyway.password=password
  flyway.schemas=dbo,custom_schema
  ```

## 7. ロールバック戦略

### 論理的なロールバック (前方向のみ)
```sql
-- V4__Revert_email_column.sql
ALTER TABLE users DROP COLUMN email;
```

### 手動ロールバック手順
1. 特定バージョンまでロールバックしたい場合:
   ```sql
   -- flyway_schema_historyテーブルから削除
   DELETE FROM flyway_schema_history WHERE installed_rank > 2;
   ```

2. データベースを手動で変更:
   ```sql
   -- V3で行った変更を手動で元に戻す
   ALTER TABLE users DROP COLUMN status;
   ```

3. 特定バージョンまで再マイグレーション:
   ```bash
   flyway -target=2 migrate
   ```

### ベースラインリセット (緊急時)
```bash
# 強制的に新ベースラインを設定
flyway baseline -baselineVersion=2 -baselineDescription="Emergency reset"
```

## 8. チーム開発のベストプラクティス

### ブランチ戦略
- タイムスタンプベースのバージョニングを使用
- マイグレーションの目的ごとにファイルを分割
- 1つのマージリクエストには関連マイグレーションをまとめる

### レビュープロセス
- アプリケーションコード変更とDB変更を同一PRで確認
- マイグレーションの副作用とロールバック戦略を検証
- パフォーマンス影響を確認

### 命名規則標準化
```
V{YYYYMMDDhhmmss}__{イシュー番号}_{目的}.sql
```
例: `V20240313120000__ISSUE-123_Add_user_preferences.sql`

## 9. 環境ごとの設定と運用

### 開発環境
```properties
flyway.cleanDisabled=false
flyway.outOfOrder=true
```

### テスト環境
```properties
flyway.cleanDisabled=false
flyway.outOfOrder=false
flyway.validateOnMigrate=true
```

### 本番環境
```properties
flyway.cleanDisabled=true  # 絶対にtrueに！
flyway.outOfOrder=false
flyway.validateOnMigrate=true
flyway.baselineOnMigrate=false
```

### CI/CD統合
```yaml
# GitLab CI例
database_migration:
  stage: migrate
  script:
    - flyway -url=$DB_URL -user=$DB_USER -password=$DB_PASSWORD migrate
  only:
    - master
```

## 10. トラブルシューティング

### 一般的な問題と解決策

| 問題 | 原因 | 解決策 |
|------|------|--------|
| Migration checksum mismatch | マイグレーションファイルが変更された | 開発環境なら`flyway repair`、本番ならロールフォワード |
| Target database is newer than this version of Flyway | DBがより新しいFlywayバージョンで管理された | Flywayを最新版に更新 |
| Migration version not in sequence | バージョン番号の順序が正しくない | タイムスタンプ方式に変更するか`outOfOrder=true`を設定 |
| Validate failed | 既に適用されたマイグレーションが変更された | `flyway repair`かベースラインリセット |

### リペア機能
```bash
# チェックサムを修正（開発環境のみ！）
flyway repair
```

## 11. 高度な機能と応用

### プレースホルダー置換
```sql
-- V1__Create_${schema_prefix}_users.sql
CREATE TABLE ${schema_prefix}_users (
    id ${id_type} PRIMARY KEY,
    username VARCHAR(100) NOT NULL
);
```

```properties
# 設定
flyway.placeholders.schema_prefix=app
flyway.placeholders.id_type=SERIAL
```

### コールバックと拡張
```sql
-- beforeMigrate.sql (in callbacks directory)
-- マイグレーション前に実行される
INSERT INTO audit_log (event) VALUES ('Migration started');
```

### Javaベースマイグレーション
```java
public class V4__Complex_migration implements JdbcMigration {
    public void migrate(Connection connection) throws Exception {
        // 複雑なマイグレーションロジック
    }
}
```

## 12. マイグレーションツール選択のポイント

| ニーズ | おすすめツール |
|--------|--------------|
| シンプルさ重視 | Flyway |
| より詳細な制御 | Liquibase |
| Python環境 | Alembic |
| Node.js環境 | Prisma Migrate |
| Ruby/Rails環境 | Rails Migrations |
| 複雑な変換・データ移行 | Liquibase |

## 13. まとめとリソース

### チェックリスト
- [ ] マイグレーションバージョニング戦略を決定（タイムスタンプ推奨）
- [ ] DBMSに合わせた正しい設定ファイル準備
- [ ] 環境ごとの設定ファイル分離
- [ ] チーム全体への教育とプロセス統一
- [ ] CI/CDパイプラインへの組み込み

### 参考リソース
- [Flyway公式ドキュメント](https://flywaydb.org/documentation/)
- [Liquibase公式ドキュメント](https://docs.liquibase.com/)
- [実践データベースマイグレーション](https://martinfowler.com/articles/evodb.html)