🗄️
Prisma Migration vs DB Push: 本番環境での正しい選択とトラブルシューティング
はじめに
Prismaを使った開発でprisma db push
とprisma 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
);
実行判定プロセス
-
prisma/migrations/
フォルダをスキャン -
_prisma_migrations
テーブルの記録と照合 - 未実行のマイグレーションを時系列順に実行
- 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
解決:
- ベースラインマイグレーションを設定
- GitHubにプッシュ
- 本番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
を使用しましょう。既存プロジェクトの移行も、ベースラインマイグレーションを使えば安全に行えます。
質問やフィードバックがあれば、ぜひコメントでお知らせください!
Discussion