Skip to content

引言

当你第一次使用 Prisma 的 migrate 命令时,感觉就像拥有了魔法。你只是在 schema.prisma 文件里改了几行定义,终端里敲下一行命令,数据库的表结构就自动、精准地更新了。它甚至还贴心地在 prisma/migrations 目录下为你创建了一个带时间戳的 SQL 文件,记录了这次变更。

一切都如此丝滑。

然后,一个很自然的想法就会冒出来:随着项目迭代,migrations 目录下的文件越来越多,几十个、上百个……我能不能在项目稳定后,把这些旧的历史文件删掉,用当前的 schema.prisma 生成一个全新的、干净的“初始迁移”文件呢?

答案是:绝对,绝对不能!

如果你这么做了,就等于亲手埋下了一颗未来随时可能引爆的定时炸弹。要理解原因,我们必须揭开 Prisma 迁移的“黑魔法”,看看那些历史文件到底扮演了多么重要的角色。

为什么?

误区:schema.prisma 就是一切?

很多人认为,schema.prisma 文件是迁移的“唯一真理之源”。Prisma 不就是靠它来生成 SQL 的吗?

这个理解只对了一半。更准确地描述是:

  • schema.prisma 是你的【最终设计蓝图】。它描述了你希望你的数据库 最终 变成什么样子。
  • prisma/migrations 目录是你的【施工日志】。它记录了从一片空地到建成这座宏伟大厦的 每一个精确步骤

你不能拿着最终蓝图,烧掉施工日志,然后期望一个新的施工队能分毫不差地重建出一座功能(数据)和结构都完全相同的大楼。

关键场景:当迁移不只是“结构变更”

数据库的演进,远比加个字段、删个表要复杂。最棘手的情况是 包含数据转换的迁移

让我们看一个经典的例子: 最初,你的用户表有两个字段:firstNamelastName。后来,为了统一,产品决定将它们合并成一个 fullName 字段。

一个正确的迁移过程是三步走:

  1. 第一次迁移(创建新字段):你在 schema.prisma 里加上 fullName 字段,然后运行 prisma migrate dev。这会生成一个 SQL 文件,在数据库中 ADD COLUMN "fullName"
  2. 数据转换(最关键的一步):你运行一个脚本,或者直接在生成的 SQL 迁移文件中手动添加一行 UPDATE "User" SET "fullName" = "firstName" || ' ' || "lastName";这个指令,将历史数据正确地迁移到了新字段里。
  3. 第二次迁移(删除旧字段):你从 schema.prisma 中删除 firstNamelastName,再次运行迁移命令,生成一个 DROP COLUMN 的 SQL 文件。

这套组合拳下来,你的数据库不仅结构对了,数据也完美无缺。

现在,想象一下,如果你删除了这些历史迁移文件,然后基于只有 fullNameschema.prisma 创建一个“压扁”后的新迁移。会发生什么?

那个至关重要的 UPDATE 数据转换指令,它消失了,永远地消失了

灾难会如何发生?答案就在于代码和数据库状态的冲突。

  • 对于新环境:一个新同事拉取你的代码,他可以创建出正确的表结构,但他的数据库里完全没有那个“合并姓名”的数据逻辑。
  • 对于老环境:当你尝试在充满历史数据的生产库上应用这个“全新的”迁移时,会发生如下致命冲突:
    1. Prisma 的迁移引擎首先连接到你的生产数据库,查看那张名为  _prisma_migrations  的历史表
    2. 它在这张表里看到了一条完整的演进记录:v1v2...v10v11  等等。这是数据库自己记载的“施工日志”。
    3. 然后,Prisma 查看你的项目代码,发现  prisma/migrations  目录里却只有一个文件:V1_baseline...
    4. 冲突爆发!  数据库里的历史记录和你代码里的历史记录完全不匹配。Prisma 不知道该相信谁,为了防止数据损坏或丢失,它会立刻中止操作,并抛出“迁移历史不一致”的严重错误。

历史文件的神圣职责 (与历史表的共舞)

所以,prisma/migrations 目录里的每一个文件都是神圣的,它们与数据库里的 _prisma_migrations 表一起,构成了你数据库健康运作的保障。

  • 代码 (prisma/migrations  目录):定义了数据库应该如何一步步演进的标准蓝图
  • 数据库 (_prisma_migrations  表):记录了当前这个数据库实例实际上已经走到了哪一步

两者必须能够步步对应,才能保证迁移的可靠性和一致性。

它们共同保证了:

  1. 可重复性:任何时候,在任何一个空数据库上,只要按顺序执行完所有迁移文件,就能 100%复现出当前生产环境的数据库,并且  _prisma_migrations  表也会被相应地填满。
  2. 一致性:保证了团队里每个成员、每个 CI/CD 环境、每个服务器的数据库结构和演进路径都是完全一致的。
  3. 完整性:不仅记录了结构(DDL),还承载了可能存在的数据转换逻辑(DML),保证了数据的延续和正确。

如何看待日益增多的文件?

“可是文件真的会变得很多啊!” 没错,这是一个现实问题。

但首先,这些纯文本文件对 Git 仓库的体积影响微乎其微。其次,社区和 Prisma 团队也在积极探索“迁移压扁”(Migration Squashing)的官方支持。但在那一天到来之前,最安全、最专业的做法就是:

prisma/migrations 目录当作你项目源代码的核心资产,完整地、按顺序地将它提交到版本控制中。

下次当你再看到那个不断增长的目录时,别再嫌它冗长了。你应该感到安心,因为那是你项目稳定性的坚实基石,是你能在数据库层面高枕无忧的根本保证。

Released under the MIT License.