🗄️

Prisma Migration vs DB Push: 本番環境での正しい選択とトラブルシューティング

に公開

はじめに

Prismaを使った開発でprisma db pushprisma migrateのどちらを使うべきか迷ったことはありませんか?本記事では、実際の本番環境でのトラブルシューティング経験を基に、両者の違いと正しい使い分け、そしてマイグレーション履歴の同期問題の解決方法を詳しく解説します。

TL;DR

  • 開発初期: db pushで高速イテレーション
  • 本番環境: 必ずmigrateでバージョン管理
  • 既存DBへの移行: ベースラインマイグレーションを設定
  • CI/CD: migrate deployで自動化

prisma db push vs prisma migrateの違い

prisma db push

npx prisma db push

特徴:

  • スキーマを即座にデータベースに反映
  • マイグレーション履歴を作成しない
  • _prisma_migrationsテーブルを作成しない
  • 既存データを考慮しない破壊的変更の可能性

適している場面:

  • プロトタイピング
  • 開発初期の頻繁なスキーマ変更
  • ローカル開発環境
  • データが重要でない環境

prisma migrate

# 開発環境
npx prisma migrate dev --name add_user_table

# 本番環境
npx prisma migrate deploy

特徴:

  • SQLマイグレーションファイルを生成
  • _prisma_migrationsテーブルで履歴管理
  • ロールバック可能(手動)
  • チーム開発でのスキーマ同期が容易

適している場面:

  • 本番環境
  • チーム開発
  • スキーマ変更の履歴が必要な場合
  • CI/CDパイプライン

マイグレーション管理の仕組み

_prisma_migrationsテーブル

Prismaは以下の構造でマイグレーション履歴を管理します:

CREATE TABLE _prisma_migrations (
    id                  VARCHAR(36) PRIMARY KEY,
    checksum            VARCHAR(64) NOT NULL,
    finished_at         TIMESTAMPTZ,
    migration_name      VARCHAR(255) NOT NULL,
    logs                TEXT,
    rolled_back_at      TIMESTAMPTZ,
    started_at          TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    applied_steps_count INTEGER DEFAULT 0 NOT NULL
);

実行判定プロセス

  1. prisma/migrations/フォルダをスキャン
  2. _prisma_migrationsテーブルの記録と照合
  3. 未実行のマイグレーションを時系列順に実行
  4. checksumで整合性を検証

実践: db pushからmigrateへの移行

問題のシナリオ

既存のプロジェクトでdb pushを使っていたが、本番環境でマイグレーション管理を始めたい場合。

エラー例

Error: P3017
The migration 0_init could not be found...

Error: P3018
A migration failed to apply. Database error:
ERROR: relation "users" already exists

解決手順

1. 現在のスキーマを取得

npx prisma db pull

2. 既存のマイグレーションをクリア

rm -rf prisma/migrations/

3. ベースラインマイグレーションを作成

# マイグレーションディレクトリを作成
mkdir -p prisma/migrations/20250904_baseline

# 現在のスキーマからSQLを生成
npx prisma migrate diff \
  --from-empty \
  --to-schema-datamodel prisma/schema.prisma \
  --script > prisma/migrations/20250904_baseline/migration.sql

4. ローカルでベースラインを適用

npx prisma migrate resolve --applied 20250904_baseline

5. 本番環境でも同様に適用

DATABASE_URL="本番DB接続文字列" \
  npx prisma migrate resolve --applied 20250904_baseline

ベストプラクティス

1. 環境別の戦略

{
  "scripts": {
    "db:push": "prisma db push",
    "migrate:dev": "prisma migrate dev",
    "migrate:deploy": "prisma migrate deploy",
    "migrate:reset": "prisma migrate reset"
  }
}

2. CI/CDパイプライン

# GitHub Actions例
- name: Deploy Database
  run: |
    npx prisma migrate deploy
  env:
    DATABASE_URL: ${{ secrets.DATABASE_URL }}

3. 環境変数の管理

# .env.local
DATABASE_URL="開発DB接続文字列"

# .env.production
DATABASE_URL="本番DB接続文字列"

4. マイグレーション前のバックアップ

# PostgreSQL例
pg_dump $DATABASE_URL > backup_$(date +%Y%m%d_%H%M%S).sql

トラブルシューティング

ケース1: マイグレーション履歴の不整合

症状: Drift detectedエラー

解決:

# 現在のDBスキーマを基準に
npx prisma db pull
npx prisma migrate dev --create-only

ケース2: 失敗したマイグレーション

症状: migrate found failed migrations

解決:

-- 失敗した記録を削除
DELETE FROM _prisma_migrations 
WHERE migration_name = '失敗したマイグレーション名';

ケース3: Vercelデプロイエラー

症状: ビルド時にrelation already exists

解決:

  1. ベースラインマイグレーションを設定
  2. GitHubにプッシュ
  3. 本番DBでも同じベースラインを適用

推奨ワークフロー

開発フェーズ

本番デプロイ

まとめ

db pushを使うべき時

  • ✅ プロトタイピング
  • ✅ 個人プロジェクトの初期開発
  • ✅ テスト環境のリセット
  • ❌ 本番環境
  • ❌ チーム開発

migrateを使うべき時

  • ✅ 本番環境
  • ✅ チーム開発
  • ✅ CI/CD統合
  • ✅ スキーマ変更の履歴管理
  • ❌ 頻繁な実験的変更

実装例

完全な実装例は以下のリポジトリで確認できます:

# package.json
{
  "scripts": {
    "prisma:generate": "prisma generate",
    "prisma:studio": "prisma studio",
    "migrate:dev": "dotenv -e .env.local -- prisma migrate dev",
    "migrate:deploy": "prisma migrate deploy",
    "migrate:reset": "prisma migrate reset"
  }
}

参考リンク

最後に

db pushは開発速度を上げる素晴らしいツールですが、本番環境では必ずmigrateを使用しましょう。既存プロジェクトの移行も、ベースラインマイグレーションを使えば安全に行えます。

質問やフィードバックがあれば、ぜひコメントでお知らせください!

GitHubで編集を提案

Discussion