mcpField
D
database-migration

database-migration

github.com/seb1nデータ・データベース236129 回インストール12 週間前に更新
リポジトリ

database-migration について

database-migration は、AI エージェントによるバージョン管理されたデータベーススキーマ変更を支援するスキルです。データベースを進化させる開発チーム向けに、ロールバック、データバックフィル、ゼロダウンタイムの手法と複数の移行フレームワークを扱います。

主な機能

  1. 01スキーマ変更リスクの評価
  2. 02アップグレードとロールバック用スクリプトの作成
  3. 03データバックフィルへの対応
  4. 04エクスパンド・アンド・コントラクト移行の計画
  5. 05ステージング環境での検証
  6. 06デプロイ後の状態監視

活用シーン

  1. 01新しいカラムの移行スクリプト作成
  2. 02データベースカラムの安全な名前変更
  3. 03本番環境への段階的デプロイ計画
  4. 04CI でのアップグレードとロールバックのテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/seb1n/awesome-ai-agent-skills --skill database-migration

インストール後、Claude Code で/database-migrationを入力して読み込まれたか確認します。

詳細

データベースのマイグレーション

このスキルを使用すると、AI エージェントはマイグレーションフレームワークを通じて、バージョン管理されたデータベーススキーマの変更を管理できます。エージェントは、適用およびロールバック用のマイグレーションスクリプトを作成し、スキーマ変更時のデータのバックフィルを処理し、安全なマイグレーションパターンでダウンタイムゼロのデプロイを実現して、マイグレーションのワークフローを CI/CD パイプラインに統合します。Alembic(Python/SQLAlchemy)、Prisma Migrate(TypeScript/Node)、Flyway(Java/SQL)、Knex(JavaScript)などの主要なツールに対応しています。

ワークフロー

  1. スキーマ変更を評価する: 列の追加、テーブルの作成、制約の変更、フィールド名の変更、データの変換など、要求された変更を分析します。変更を後方互換性のあるもの(追加)か、破壊的なもの(削除など)かに分類し、デプロイ戦略を決定します。破壊的な変更には、複数フェーズのマイグレーションが必要です。

  2. マイグレーションツールを選択する: プロジェクトの技術スタックに基づいて、適切なマイグレーションフレームワークを選択します。Python/SQLAlchemy プロジェクトには Alembic、TypeScript/Prisma プロジェクトには Prisma Migrate、Java または SQL ファーストのワークフローには Flyway、Node.js/Express プロジェクトには Knex を使用します。ツールが初期化され、対象データベースに接続されていることを確認します。

  3. マイグレーションスクリプトを生成する: 対応している場合は、スキーマ差分からマイグレーションを自動生成します(Alembic の autogenerate、Prisma の migrate dev)。その後、生成されたスクリプトを確認して編集します。明示的なロールバック(ダウングレード)ロジックを追加します。データのバックフィルでは、スキーマとデータの変更をアトミックに保つため、データ変換をマイグレーションに含めます。

  4. ステージング環境でテストする: 本番環境を再現したステージングデータベースにマイグレーションを適用します。問題なく適用されること、既存のクエリが引き続き動作すること、ロールバックによって以前の状態に復元されることを確認します。マイグレーション後のスキーマに対して、アプリケーションのテストスイートを実行します。

  5. ダウンタイムゼロの戦略でデプロイする: 本番環境では、拡張と縮小によるマイグレーションを使用します。フェーズ 1:古い構造を削除せずに、新しい列やテーブルを追加します(拡張)。フェーズ 2:古い構造と新しい構造の両方に書き込むアプリケーションコードをデプロイします。フェーズ 3:データをバックフィルします。フェーズ 4:新しい構造のみを使用するコードをデプロイします。フェーズ 5:古い列やテーブルを削除します(縮小)。これにより、ダウンタイムを防ぎ、各フェーズで安全にロールバックできます。

  6. 検証して監視する: デプロイ後、フレームワークのステータスコマンドでマイグレーションの状態を確認します。アプリケーションログとデータベースのパフォーマンスを監視し、問題がないか確認します。すべてのマイグレーションのメタデータが、フレームワークのバージョンテーブルに記録されていることを確認します。

対応技術

  • Alembic: Python、SQLAlchemy、PostgreSQL/MySQL/SQLite
  • Prisma Migrate: TypeScript/JavaScript、Prisma ORM、PostgreSQL/MySQL/SQLite/SQL Server
  • Flyway: Java、SQL ベースのマイグレーション、主要な RDBMS 全般
  • Knex: JavaScript/TypeScript、Node.js、PostgreSQL/MySQL/SQLite
  • Django Migrations: Python、Django ORM
  • Sequelize: JavaScript、Node.js ORM

使用方法

必要なスキーマ変更(例:「users テーブルに phone_number 列を追加する」)を説明し、プロジェクトで使用しているマイグレーションフレームワークを指定してください。エージェントはアップグレードとダウングレードのロジックを含むマイグレーションファイルを生成し、適用手順を示して、本番環境での安全なデプロイ戦略について助言します。

例

例 1:Alembic のマイグレーション — データのバックフィルを伴う列の追加

依頼: users テーブルに display_name 列を追加し、first_name と last_name を連結してバックフィルしてください。

マイグレーションを生成する:

alembic revision --autogenerate -m "add_display_name_to_users"

マイグレーションファイル(versions/20250115_add_display_name_to_users.py):

"""add display_name to users

Revision ID: a1b2c3d4e5f6
Revises: 9z8y7x6w5v4u
Create Date: 2025-01-15 10:30:00.000000
"""
from alembic import op
import sqlalchemy as sa

revision = "a1b2c3d4e5f6"
down_revision = "9z8y7x6w5v4u"
branch_labels = None
depends_on = None


def upgrade():
    # Phase 1: Add the column as nullable (safe, no locks on reads)
    op.add_column("users", sa.Column("display_name", sa.String(300), nullable=True))

    # Phase 2: Backfill existing rows
    users = sa.table(
        "users",
        sa.column("id", sa.Integer),
        sa.column("first_name", sa.String),
        sa.column("last_name", sa.String),
        sa.column("display_name", sa.String),
    )
    op.execute(
        users.update().values(
            display_name=sa.func.concat(
                users.c.first_name, " ", users.c.last_name
            )
        )
    )

    # Phase 3: Set NOT NULL after backfill is complete
    op.alter_column("users", "display_name", nullable=False)


def downgrade():
    op.drop_column("users", "display_name")

適用して検証する:

alembic upgrade head
alembic current   # Confirms: a1b2c3d4e5f6 (head)
例 2:Prisma Migrate — Review モデルの追加

依頼: Prisma プロジェクトで、User と Product に関連付けられた Review モデルを追加してください。

prisma/schema.prisma を更新する:

model Review {
  id        Int      @id @default(autoincrement())
  rating    Int      @db.SmallInt
  comment   String?  @db.Text
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  userId    Int
  productId Int
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  product   Product  @relation(fields: [productId], references: [id], onDelete: Cascade)

  @@unique([userId, productId])
  @@index([productId])
  @@index([rating])
}

マイグレーションを生成して適用する:

npx prisma migrate dev --name add_reviews_table

生成された SQL(prisma/migrations/20250115_add_reviews_table/migration.sql):

CREATE TABLE "Review" (
    "id" SERIAL NOT NULL,
    "rating" SMALLINT NOT NULL,
    "comment" TEXT,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,
    "userId" INTEGER NOT NULL,
    "productId" INTEGER NOT NULL,
    CONSTRAINT "Review_pkey" PRIMARY KEY ("id")
);

CREATE INDEX "Review_productId_idx" ON "Review"("productId");
CREATE INDEX "Review_rating_idx" ON "Review"("rating");
CREATE UNIQUE INDEX "Review_userId_productId_key" ON "Review"("userId", "productId");
ALTER TABLE "Review" ADD CONSTRAINT "Review_userId_fkey"
    FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE;
ALTER TABLE "Review" ADD CONSTRAINT "Review_productId_fkey"
    FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE;

ベストプラクティス

  • **すべてのマイグレーションに、明示的なダウングレード/ロールバック処理を必ず記述してください。**デプロイで問題が発生した場合に、安全に元に戻せるようにします。切迫した状況で手動でマイグレーションを取り消せると決めつけないでください。
  • **expand-and-contract の手法を使い、マイグレーションに後方互換性を持たせてください。**まず新しい構造を追加し、次にデータを移行します。その後、新しいコードのデプロイが完全に完了してから、別のマイグレーションで古い構造を削除します。
  • **自動生成されたマイグレーションを、確認せずに実行しないでください。**自動検出ツールは、名前が変更されたフィールドを見つけたときに、カラムの削除など破壊的な操作を生成することがあります。生成された SQL は必ず確認してください。
  • サポートされている場合は、DDL にトランザクションを使用してください(PostgreSQL は DDL をトランザクションでラップしますが、MySQL はしません)。トランザクションに対応していない DDL データベースでは、部分的な失敗からの復旧を計画してください。
  • **マイグレーションは小さく、目的を絞ったものにしてください。**マイグレーションファイルごとに、論理的な変更を 1 つだけ行います。これにより、ロールバックの範囲を細かくでき、問題の原因となったマイグレーションを特定しやすくなります。
  • **CI で使い捨てのデータベースに対してマイグレーションを実行し、本番環境に到達する前にエラーを検出してください。**テストにはアップグレードとダウングレードの両方の経路を含めてください。

エッジケース

  • **大きなテーブルのマイグレーション:**数百万行あるテーブルに、デフォルト値付きの NOT NULL カラムを追加すると、古いバージョンの PostgreSQL では数分間テーブルがロックされることがあります。ADD COLUMN ... DEFAULT ... NOT NULL(PostgreSQL 11 以降ではロックフリー)を使用するか、まず NULL 許容として追加し、バッチでバックフィルしてから NOT NULL に設定してください。
  • **カラム名の変更:**多くのマイグレーションツールは名前の変更を削除+追加として扱うため、データが失われます。Alembic の op.alter_column() または生の ALTER TABLE ... RENAME COLUMN を使って、実際の名前変更を行ってください。適用前に、生成されたマイグレーションを確認してください。
  • **同時マイグレーション:**複数インスタンスでのデプロイでは、マイグレーションを実行するインスタンスが 1 つだけになるようにしてください。アドバイザリロック(Flyway と Alembic がサポートしています)を使用するか、アプリケーションインスタンスのローリングデプロイ前に専用のステップとしてマイグレーションを実行するデプロイパイプラインを使用してください。
  • **Enum 型の変更:**PostgreSQL で値を Enum に追加する操作は、トランザクションに対応していません。新しい Enum 型を作成し、カラムを移行してから、古い型を削除してください。あるいは、変更しやすいように CHECK 制約付きの VARCHAR を使用してください。
  • **データのみのマイグレーション:**スキーマを変更せずにデータを変換する必要がある場合(例:カラムの値を暗号化する場合)でも、環境間でバージョン管理と再現ができるよう、マイグレーションファイルを使用してください。

コメント