Prismaのマイグレーションで失敗する原因|migrate devとdb pushの違い
PrismaでWebアプリを開発していると、必ずどこかでこの壁にぶつかります。
prisma migrate devを実行したら権限エラーで止まったdb pushで開発してきたが、本番環境にどう反映すればいいか分からない--accept-data-lossを付けろと言われたが、何が消えるのか判断できない- スキーマを変更したのに型が更新されない
PrismaはTypeScript向けのORM(データベース操作をコードから型安全に扱う仕組み)で、テーブル定義をschema.prismaというファイルで管理します。この定義を実際のデータベースに反映する方法が2通りあることが、混乱の出発点です。
migrate dev と db push は、どちらを使えばいいのか。
結論から言えば、この2つは優劣ではなく目的が違います。公式ドキュメントの記述をもとに整理します。
3つのコマンドの役割
まず全体像です。Prismaのスキーマ反映には、用途の異なる3つのコマンドがあります。
| コマンド | 使う場面 | 履歴 |
|---|---|---|
db push |
試行錯誤中の開発 | 残さない |
migrate dev |
設計が固まった開発 | 残す |
migrate deploy |
本番・テスト環境への反映 | 適用のみ |
この「履歴」がすべての違いを生みます。
db push は履歴を残さない
db pushは、スキーマファイルの内容にデータベースを合わせるコマンドです。今の状態から目標の状態へ最短で移すことだけを行います。
公式ドキュメントはこう説明しています。
Prisma Migrateとは異なり、db pushはデータを保持するために修正できるマイグレーションを生成しない。したがって開発環境でのプロトタイピングに最も適している
さらに、履歴が残らないことについても明記されています。
最初のプロトタイプに至るまでの手順は保存されない。db pushは履歴を生成しない
データベースの変更履歴を記録する_prisma_migrationsテーブルも作成されず、SQLファイルも残りません。つまり「どう変わってきたか」を後から追えません。
見落としやすい落とし穴
もう1点、公式が注意している挙動があります。
ジェネレーター(Prisma Clientなど)を自動的に起動しない。スキーマ変更後は手動で
prisma generateを実行する必要がある
冒頭に挙げた「スキーマを変更したのに型が更新されない」は、多くの場合これが原因です。db pushを使う場合は、prisma generateをセットで実行する習慣が必要になります。
データが消える場合は止まる
乱暴なコマンドに見えますが、安全装置はあります。
db pushが変更によってデータ損失が起こりうると判断した場合、エラーを発生させ、それでも実行したい場合は
--accept-data-lossオプションを要求する
このオプションを求められたら、実際にデータが失われる変更だということです。列の削除や型変更が典型例で、開発中のダミーデータなら問題ありませんが、内容を確認せずに付けるのは危険です。
migrate dev の裏側:シャドウデータベース
一方のmigrate devは、変更内容をSQLファイルとして記録します。この裏側で、意外な仕組みが動いています。
シャドウデータベースは、
prisma migrate devを実行するたびに自動的に作成・削除される2つ目の一時的なデータベースであり、主にスキーマドリフトや、生成されるマイグレーションによるデータ損失の可能性といった問題を検出するために使われる
実行のたびに、裏で別のデータベースが作られて消えているわけです。
何のために必要なのか
目的はスキーマドリフトの検出です。ドリフトとは、マイグレーション履歴と実際のデータベースの状態がずれることを指します。
たとえば、誰かが管理ツールから直接テーブルを変更したとします。履歴上は存在しない変更なので、次に誰かがマイグレーションを実行したとき、想定と違う結果になりかねません。
そこでPrismaは、まっさらなシャドウDBに履歴を最初から再実行し、「履歴どおりに作った状態」と「実際の状態」を比較します。差があればドリフトとして警告します。
【頻出】クラウドDBで migrate dev が失敗する理由
ここが実務で最もつまずく箇所です。シャドウDBはその場で作られて消されるため、データベースを作成する権限が必要になります。
migrate devを使う際、Prisma Migrateは現在、datasourceで定義されたデータベースユーザーにデータベースを作成する権限があることを要求する
権限要件はデータベースによって異なります。
| データベース | 要件 |
|---|---|
| SQLite | 特別な要件なし |
| MySQL / MariaDB | CREATE・ALTER・DROP等の権限が必要 |
ローカルのSQLiteで開発していると何の問題も起きませんが、クラウドのマネージドデータベースでは話が変わります。セキュリティ上、アプリケーション用のユーザーにデータベース作成権限を与えないのが一般的だからです。
公式もこのケースを想定しています。
データベースが作成と削除を許可しない場合(クラウドホスト環境など)、シャドウデータベースを手動で作成し設定する必要がある
設定時の重大な注意点
手動設定ではshadowDatabaseUrlに別のデータベースを指定しますが、公式は強い警告を出しています。
urlとshadowDatabaseUrlにまったく同じ値を使用してはならない。データベース内のすべてのデータが削除される可能性がある
シャドウDBは中身を消して作り直す前提の領域です。ここに本番や開発用のDBを指定すると、データが消えます。設定ミスの代償が大きい項目なので、必ず専用のデータベースを用意してください。
なお、シャドウDBが必要なのは開発時だけです。公式は「シャドウデータベースは本番では必要なく、migrate deployのような本番向けコマンドでは使用されない」と明記しています。
本番への反映は migrate deploy
本番環境ではmigrate devを使いません。適用専用のmigrate deployを使います。
migrate deployは一般に自動化されたCI/CDパイプラインの一部であるべきで、本番データベースへ変更を反映するためにこのコマンドをローカルで実行することは推奨しない
手元から本番のデータベースを直接書き換える運用は、公式が明確に非推奨としています。デプロイ手順の中に組み込むのが正しい形です。なお、無停止でのリリースを目指す場合は、ブルーグリーンデプロイのようにスキーマ変更を後方互換に保つ設計が前提になります。
公式が推奨する進め方
2つのコマンドは対立するものではなく、段階的に使い分けるのが公式の想定です。
- 設計が固まっていない段階:
db pushで素早く試す。テーブル構成を何度も作り変える時期は、履歴を残すほうが邪魔になります - 形が見えてきたら:
prisma migrate dev --name initial-stateを実行し、その時点の状態を最初のマイグレーションとして記録します - 以降の変更:
migrate devで履歴を積み上げます - 本番反映:
migrate deployをCI/CDから実行します
ポイントは、チーム開発や本番運用が始まった時点で履歴管理へ移行することです。履歴がなければ、他のメンバーや本番環境に同じ変更を再現できません。
Prisma 7 での変更点
2026年時点の最新はPrisma 7系です。マイグレーション作業に影響する変更があるため、v6から上げる場合は注意が必要です。
特に見落としやすいのが環境変数の扱いです。
Prisma ORM 7.0.0では、環境変数が既定で読み込まれない。開発者はPrisma CLIを呼び出す際に明示的に変数を読み込む必要がある
v6までは.envが自動で読まれていたため、アップグレード直後に「DATABASE_URLが見つからない」というエラーで止まることがあります。dotenvなどで明示的に読み込む対応が必要です(Bunを使っている場合は自動で読み込まれるため対応不要とされています)。
設定はprisma.config.tsに集約する形に変わり、shadowDatabaseUrlもここで指定します。またMongoDBはv7では未対応で、公式は当面v6の使用を推奨しています。
よくある質問
Q. db pushだけで開発を進めてはいけませんか?
一人で開発していて本番運用もない段階なら問題ありません。ただし誰かと共有する時点で履歴が必要になります。後からでもmigrate devで履歴を開始できるため、切り替えのタイミングを逃しても対応可能です。
Q. シャドウデータベースは自分で用意する必要がありますか?
ローカルのSQLiteやPostgreSQLで、データベース作成権限があれば自動で処理されます。権限が制限された環境でのみ、手動設定が必要です。
Q. マイグレーションファイルは編集してもよいですか?
生成されたSQLを編集することは可能で、公式もカスタマイズ方法を案内しています。ただしすでに適用済みのファイルを後から書き換えるのは危険です。migrate deployは適用済みマイグレーションと履歴を比較し、変更されていれば警告を出します。
Q. –accept-data-lossは付けても大丈夫ですか?
開発中のテストデータであれば問題ありません。実データが入っている環境では絶対に避けてください。どの列が消えるのかを確認したうえで判断すべきオプションです。
Q. 本番でmigrate devを実行するとどうなりますか?
シャドウデータベースの作成が試みられるほか、状況によってはリセットを促されることがあります。本番では必ずmigrate deployを使ってください。
参考にした主な調査・資料
- Prototyping your schema(Prisma)— db pushの挙動、履歴を生成しないこと、データ損失時の警告
- About the shadow database(Prisma)— シャドウデータベースの役割と権限要件
- Development and production(Prisma)— 本番環境でのmigrate deployの位置づけ
- Upgrade to Prisma ORM 7(Prisma)— v7の変更点、環境変数の扱いとMongoDB対応状況
まとめ
2つのコマンドは、優劣ではなく役割の違いです。
db pushは履歴を残さず、スキーマの状態に合わせるだけ。試行錯誤の段階に向くdb pushはprisma generateを自動実行しない。型が更新されない原因になるmigrate devは裏でシャドウデータベースを作り、スキーマドリフトを検出する- そのためデータベース作成権限が必要。クラウド環境で失敗する主因
shadowDatabaseUrlに本番と同じ値を設定してはいけない。データが消える- 本番反映は
migrate deployをCI/CDから実行する - Prisma 7では環境変数が自動で読み込まれない
迷ったときは「この変更を、他の人や本番環境で再現する必要があるか」を基準にしてください。必要ならmigrate、不要ならpushです。