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

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` のようにコピーするだけで取れます。日時を付けて残し、問題が起きたら書き戻せば元の状態に戻せます。