首页 / Prisma ORM 入门教程 / 迁移的心智模型:历史、影子库与漂移

Prisma ORM 入门教程

迁移的心智模型:历史、影子库与漂移

本教程共 54 篇 · 第 29 篇 · 更新于 2026-08-11 · 约 6 分钟阅读

Prisma迁移Prisma Migrate影子数据库Schema 漂移迁移历史checksum

本节目标:理解迁移的本质——数据库 Schema(模式)的版本控制;认识迁移历史、迁移表、影子数据库三件套,以及为什么已应用的迁移碰不得。

数据库也需要版本控制

代码用 Git 管版本,数据库的结构却常常没人管。上线后有人手动加了列,开发环境改过表结构,几个月后没人说得清生产库长什么样。迁移(migration)就是给数据库结构做的版本控制:每次结构变更记录成一份 SQL 文件,按顺序应用,随时可以重放。

演进 Schema 有两条路线:

  • 模型优先:先用代码定义结构,再由迁移工具生成 SQL 应用到数据库。Prisma Migrate 走这条路。
  • 数据库优先:先用 SQL 建库,再通过内省(Introspection)反向生成代码。db pull 属于这条线。

本部分讨论的都是模型优先。

四份状态

Prisma Migrate 靠四份状态跟踪数据库:

  1. Prisma Schema:唯一源头,描述目标结构
  2. 迁移历史prisma/migrations/ 下的 SQL 文件
  3. 迁移表:数据库里的 _prisma_migrations 表,记录已应用的迁移
  4. 数据库本身:实际的表结构

Schema 是「应该长什么样」,迁移表是「已经做了什么」,数据库是「现在长什么样」。三者一致,一切正常;不一致,就出问题。

开发环境的三个前提

Prisma Migrate 对开发环境有几个要求:

  1. 每个环境一个数据库:开发、预览、生产各用各的库
  2. 开发库可以随意丢弃:随时能建、能删、能重置
  3. 各环境数据库配置一致:同一份迁移在不同环境产生相同结果

前两条保证了「重置数据库」是低成本操作,第三条保证了迁移历史在各地重放结果一致。如果你的数据库托管在云端、不允许自由建删库,开发环境就要单独准备一个影子数据库(下文会讲)。

migrations/ 目录与 migration_lock.toml

每次 migrate dev 都会生成一个以时间戳命名的文件夹:

prisma/migrations/
├── migration_lock.toml
└── 20260811120000_init/
    └── migration.sql

时间戳就是应用顺序——迁移按字典序执行。整个目录必须提交进版本库:migrate deploy 只认迁移文件,不读 Schema;而且手改过的迁移里藏着 Schema 表达不了的信息(比如数据回填 SQL),丢了就再也找不回。

migration_lock.toml 记录数据库厂商(provider)。它防止你中途换库:迁移文件是厂商相关的 SQL,PostgreSQL 的语法不能用在 SQLite 上。强行切换会报错 P3019(provider 与 migration_lock.toml 不匹配,部分旧文档写作 P3014),提示清空迁移历史重新开始。

_prisma_migrations 表:带 checksum 的账本

迁移应用到数据库后,_prisma_migrations 表会记一笔账:迁移名、应用时间、错误日志,还有一个 checksum(校验和)。

checksum 是迁移文件内容的哈希。再次运行迁移命令时,Prisma 会重新计算文件哈希,和账本里的比对。一旦对不上,就说明有人改过已应用的迁移——这被视为「迁移历史冲突」。

Note

分工不同:影子数据库负责检测结构漂移,checksum 负责检测文件被篡改。

影子数据库:漂移检测器

影子数据库(shadow database)是 migrate dev 运行时临时创建、用完即删的数据库,主要干四件事:

  1. 把现有迁移历史在影子数据库里重放一遍
  2. 内省影子数据库,得到「历史终点」的结构
  3. 与你的开发数据库对比,发现意外改动——这就是漂移(schema drift)检测
  4. 生成新迁移,并评估是否会导致数据丢失

开发库被手动改过(比如手敲了 SQL),对比就会报漂移,migrate dev 会提示重置数据库,并具体列出差异。例如枚举类型缺了 RED 变体、多了 TRANSPARENT 变体,输出会逐项标出 [+] 新增和 [-] 移除。

Note

影子数据库只在开发环境需要。migrate deploymigrate resolve 这些生产命令完全不碰它。

本地 PostgreSQL 用户需要 CREATEDB 权限。云数据库(如 Heroku、Vercel Postgres)不允许自动建库,要在 prisma.config.ts 里手动指定:

datasource: {
  url: env("DATABASE_URL"),
  shadowDatabaseUrl: env("SHADOW_DATABASE_URL"),
},
Warning

shadowDatabaseUrl 绝不能和 url 指向同一个库,否则迁移过程会清空你的数据。

db push:不记历史的同步

快速原型阶段可以先用 prisma db push:它直接把 Schema 同步到数据库,不生成迁移文件、不记录历史。适合丢弃型实验。但它无法预览变更、无法编排数据迁移,检测到破坏性变更只会提示重置——所以正式项目从第一天就该用迁移。

已应用的迁移不可编辑

迁移一旦应用,就是历史。修改已应用的迁移文件(哪怕只是把 VARCHAR(550) 改成 VARCHAR(560)),会导致开发与生产的历史分叉:开发环境重置后能重放,生产环境却永远带着旧文件,migrate deploy 从此每次都会警告「以下迁移已被修改」。

这种「看似无害」的改动最危险:重置后重放一切正常,你会以为没事,但生产环境的警告会一直存在,哪天改动涉及高度定制的迁移,开发与生产的行为就彻底对不上了。

正确的姿势:用新迁移修正旧迁移。想要 560,就新建一个迁移把列改过去。

Tip

发现已应用的迁移被改或缺失时,优先恢复文件、还原改动,而不是重置数据库。治本,不治标。

Note

本部分所有命令仅适用于关系型数据库。MongoDB 在 v7 中不被支持,需要 MongoDB 请留在 v6.19。

参考来源

  • Prisma 官方文档:Mental model
  • Prisma 官方文档:Migration histories
  • Prisma 官方文档:Shadow database
  • Mapagam:Creating and running migrations