Prisma migrate devでデータが消える|drift回避の実践手順

※本記事にはプロモーション(広告・アフィリエイトリンク)を含みます。
prisma migrate dev を実行したら Drift detected と表示され、そのまま進めると開発DBの中身が消える——これはコマンドの仕様どおりの挙動で、知らないと初回でつまずきます。この記事は Prisma でマイグレーションを回している開発者向けに、データを消さずにスキーマを合わせる手順を、確認 → ケース別対応 → 本番運用の順で書きます。Next.js(App Router)+ TypeScript + Prisma + SQLite の構成を前提に、一般的な手順としてコマンドを挙げます。
drift(ドリフト)とは何か、なぜ消えるのか
drift とは、prisma/migrations/ に記録されたマイグレーション履歴と、実際のデータベースの状態がズレている状況を指します。Prisma 公式ドキュメントによると prisma migrate dev は開発環境専用のコマンドで、履歴とDBの不一致を検出すると、履歴どおりの状態を作り直すためにDBのリセット(=全データ削除)を提案します。プロンプトでは「リセットが必要です/続けるとデータは失われます」といった確認が出て、ここで安易に y を押すと消えます。
drift が起きる主な原因は次のとおりです。
| 原因 | 具体例 |
|---|---|
| DBを手で変更した | SQLツールや prisma db push で直接スキーマを変えた |
| 適用済みマイグレーションを編集した | 一度当てた migration.sql を後から書き換えた |
| DBを差し替えた | バックアップから別状態のDBを復元した |
| 履歴ファイルを消した/追加した | migrations/ を手で整理した |
つまり「履歴と実DBのどちらが正か」を Prisma が判断できない状態です。ここを踏まえると、対処は「まず現状を壊さず確認する」ことから始まります。
手順1: 実行する前にバックアップと状況確認
migrate dev を再度叩く前に、必ず現状を保全します。SQLite ならDBは単一ファイルなので、コピーするだけでバックアップになります。
# 触る前にDBを退避(SQLiteはファイルコピーでよい)
cp prisma/dev.db "prisma/dev.db.$(date +%Y%m%d_%H%M).bak"
# 履歴とDBの状態を確認(この時点では何も変更されない)
npx prisma migrate status
migrate status は、未適用のマイグレーションがあるか、drift が起きているか、履歴が壊れていないかを読み取り専用で教えてくれます。さらに「スキーマ定義と実DBの差分」を具体的に見たいときは migrate diff を使います。
# schema.prisma と 実DB の差分をSQLで出力(適用はしない)
npx prisma migrate diff \
--from-schema-datasource prisma/schema.prisma \
--to-schema-datamodel prisma/schema.prisma \
--script
どの方向にどれだけズレているかを把握してから、次のケース別対応に進みます。ここを飛ばして migrate dev を再実行するのが、いちばんの事故のもとです。
手順2: ケース別にデータを残して合わせる
ケースA: 実DBが正で、履歴を実DBに合わせたい
手作業やほかのツールでDBを変えてしまい、その状態を残したい場合です。実DBからスキーマを引き直し、その状態を「初期状態」として履歴に取り込みます(ベースライン化)。
# 実DBの構造を schema.prisma に取り込む
npx prisma db pull
# 現状を初期マイグレーションとして生成(DBには当てない)
npx prisma migrate dev --name baseline --create-only
# そのマイグレーションを「適用済み」として履歴に記録(DBは変更しない)
npx prisma migrate resolve --applied <生成されたフォルダ名>
--create-only は SQL ファイルだけ作ってDBには当てないオプション、migrate resolve --applied は「このマイグレーションはもう当たっている」と履歴に印を付けるだけの操作です。どちらもデータを消しません。
ケースB: 適用済みマイグレーションを編集してしまった
一度当てた migration.sql を後から書き換えると drift になります。編集を元に戻して履歴を一致させ、以後の変更は新しいマイグレーションとして追加します。過去の履歴は改変しない、が原則です。
ケースC: スキーマに新しい変更を入れたいだけ
単に列を足したいなどの通常変更なら、いきなり適用せず中身を確認してから当てます。
# SQLを生成して目視確認 → 問題なければ次で適用
npx prisma migrate dev --name add_column --create-only
cat prisma/migrations/*add_column/migration.sql
npx prisma migrate dev
生成されたSQLに DROP TABLE や意図しない DELETE がないかを確認する習慣をつけると、破壊的変更に気づけます。
手順3: 本番では migrate dev を使わない
最重要の原則です。公式ドキュメントによると prisma migrate deploy はリセットを一切行わず、未適用のマイグレーションを順に当てるだけのコマンドで、本番向けに設計されています。一方 migrate dev は前述のとおりリセットを提案するため、本番で使ってはいけません。
# 本番/ステージングで実行するのはこれだけ
npx prisma migrate deploy
自宅の Linux 機で Node アプリを systemd 常駐させて運用するような構成では、稼働中プロセスがDBファイルを開いたままマイグレーションを当てない配慮が要ります。SQLite は書き込み時にロックがかかるため、切り替えのタイミングでマイグレーションを流すようにしておくと、ロック起因のエラーを避けやすいと考えられます(挙動は環境によって異なります)。
つまずきやすい点
- シャドウデータベース:
migrate devは検証用の一時DB(シャドウDB)を作って差分を確かめます。権限が足りないとここで失敗します。SQLite ではファイルとして自動生成されますが、権限や書き込み先の問題が出たら公式のシャドウDB設定を確認してください。 db pushとmigrateの混在:prisma db pushは履歴を残さずスキーマを反映するコマンドです。試作では便利ですが、migrateと混ぜると drift の温床になります。プロジェクト内でどちらを使うか統一するのが安全です。- バージョン差: 上記のコマンド名・オプションは執筆時点(2026-10)のものです。Prisma はマイナー更新で挙動が変わることがあるため、実行前に
npx prisma --versionと公式ドキュメントを確認してください。
まとめ
migrate dev の drift によるデータ消失は、「実行前にDBをコピーし、migrate status で状況を確認する」という2手を挟むだけでほぼ防げます。まず今のプロジェクトで cp によるバックアップと npx prisma migrate status の確認を、マイグレーション前の定型作業として手順書に入れてください。それだけで、うっかり y を押す事故の被害を最小化できます。
よくある質問
prisma migrate dev と migrate deploy の違いは?
migrate dev は開発専用で、履歴とDBがズレるとリセット(データ削除)を提案します。migrate deploy はリセットせず未適用分を順に当てるだけで、本番向けです。本番では deploy だけを使います。
Drift detected と出たら必ずデータは消えますか?
検出だけならデータは消えません。消えるのはリセットの確認に同意した場合です。まずDBをコピーで退避し、migrate status と db pull や migrate resolve で履歴と実DBを合わせれば残せます。
SQLite でマイグレーション前のバックアップはどう取る?
DBが単一ファイルなので `cp prisma/dev.db prisma/dev.db.bak` のようにコピーするだけで取れます。日時を付けて残し、問題が起きたら書き戻せば元の状態に戻せます。