迁移冲突与 reset:migrate dev 报历史不一致怎么办
典型报错
Error: The database schema is not in sync with the Prisma schema.
This can happen when:
- You edited the database directly and didn't use Prisma Migrate
- You used `db push` instead of `migrate dev`
- Your migration history is out of sync with the database
Running `prisma migrate status` might help diagnose the issue.
根源
Prisma Migrate 在数据库里维护一张 _prisma_migrations 表,记录了所有已应用的迁移。同时它在本地 prisma/migrations/ 目录下保留迁移文件,还有一个快照记录 Schema 在某次迁移后的状态。
当这三者(数据库实际结构 / _prisma_migrations 表 / 本地快照)不一致时,migrate dev 就会报错。
诊断:migrate status
npx prisma migrate status
输出会告诉你:
- 数据库里已应用了哪些迁移
- 本地
migrations/目录里有哪些迁移 - Schema 和最后一次迁移快照是否一致
根据 status 输出选择修复方案。
三种常见场景与修复
场景一:手动改了数据库
你绕过 Prisma,直接在数据库客户端里加了一列、改了字段类型等。现在 Prisma 发现数据库结构和 Schema 对不上。
修复方案(选一个):
A. 把数据库的变化同步回 Schema
npx prisma db pull # 从数据库拉最新结构到 Schema
然后手动检查 Schema 里新增/变化的 model 和字段,确认没问题后 npx prisma migrate dev 继续。
B. 重置重来
如果数据库里的数据不重要(开发环境、原型阶段):
npx prisma migrate reset
这会清空数据库、重新应用所有迁移、重新 seed。最干净但会丢数据。
场景二:db push 和 migrate dev 混用了
你之前一直用 db push,突然想转 migrate dev。或者反过来。
修复方案:
- 检查
prisma/migrations/目录是否存在 - 如果不存在 → 之前用的是
db push,现在第一次跑migrate dev会提示 reset,接受 - 如果存在 → 你曾经用过 migrate dev,后来可能用了 db push。检查
migrate status看具体哪个环节错位
关键教训:选定 migrate dev 或 db push 其中一种就坚持到底。混用 = 给自己挖坑。
场景三:团队成员各自改了迁移
你和同事各自在本地跑了不同的 migrate dev --name xxx,然后合并代码时发现迁移顺序对不上。
修复方案:
# 1. 拉最新代码
git pull
# 2. 看 status
npx prisma migrate status
# 3. 如果只是数据库没跟上本地迁移——跑 deploy
npx prisma migrate deploy
# 4. 如果有冲突的迁移文件——手动合并或 reset
Prisma 的迁移是按目录名字典序执行的(不是按创建时间)。如果两个同事同时创建了 20240115_add-xxx 和 20240115_add-yyy,合并后只要按字典序能对上就行。
迁移文件手动编辑
有时候自动生成的 migration.sql 不够灵活,需要手动改。改完后:
- Prisma 会校验 migration.sql 的 checksum(防止被篡改)
- 如果 checksum 不匹配,
migrate status会提示警告 - 但迁移文件执行过后,checksum 已经存到数据库里了
如果改了一个已执行过的迁移文件,Prisma 会报 checksum mismatch。解决方案:
- 不要改已执行过的迁移——这是 Prisma 的原则。迁移一旦执行就不可变
- 应该写一个新的迁移来做你想做的修改
如果确实需要改(原型阶段、没人用生产数据),可以手动从 _prisma_migrations 表里删掉那条记录,然后 reset。
什么时候该 reset
| 情况 | 该不该 reset |
|---|---|
| 开发环境,原型阶段,数据不重要 | ✅ 随意 reset |
| 测试环境,有种子数据 | ✅ reset 后重新 seed |
| 生产环境,有真实数据 | ❌ 绝对不要。手动写修复迁移 |
| migrate status 报错了但不想手动修 | 开发/测试环境可以 reset,生产不行 |
预防
- 选定一种迁移方式就坚持到底——要么 migrate dev,要么 db push,不要混
- 不要手动改数据库——改 Schema 跑 migrate,不要在数据库客户端里直接改表结构
- 每次 migrate dev 后 commit migrations/ 目录——迁移文件跟代码一起提交
- 团队协作时先 pull 后 migrate dev——避免生成重复或冲突的迁移
- 生产环境用 migrate deploy,不要用 migrate dev——migrate dev 有能力根据 Schema 变化生成并执行新迁移,生产环境不该让它有这个权限