关于影子数据库
影子数据库是第二个临时数据库,它在您每次运行 prisma migrate dev
时自动创建和删除*,主要用于检测问题,例如模式漂移或生成的迁移可能导致的数据丢失。
migrate diff
命令 在使用 --from-migrations
或 --to-migrations
对本地 migrations
目录进行差异比较时,也需要影子数据库。
- 如果您的数据库不允许创建和删除数据库(例如在云托管环境中),您需要手动创建和配置影子数据库。
影子数据库在生产环境中不是必需的,并且不被面向生产环境的命令(如 prisma migrate resolve
和 prisma migrate deploy
)使用。
影子数据库从不用于 MongoDB,因为 migrate dev
在那里不使用。
影子数据库的工作原理
当您运行 prisma migrate dev
来创建新的迁移时,Prisma Migrate 使用影子数据库来
🎨 展开以卡通形式查看影子数据库的解释。
检测模式漂移
为了检测开发中的漂移,Prisma Migrate 会
- 创建影子数据库的全新副本(如果影子数据库是通过
shadowDatabaseUrl
配置的,则执行软重置) - 在影子数据库中重新运行当前已有的迁移历史记录。
- 内省影子数据库以生成 Prisma 模式的“当前状态”。
- 将当前迁移历史记录的最终状态与开发数据库进行比较。
- 如果当前迁移历史记录的最终状态(通过影子数据库)与开发数据库不匹配(例如,由于手动更改),则报告模式漂移
如果 Prisma Migrate 未检测到模式漂移,则继续生成新的迁移。
注意:影子数据库不负责检查迁移文件是否已被编辑或删除。 这是通过
_prisma_migrations
表中的checksum
字段完成的。
如果 Prisma Migrate 检测到模式漂移,它会输出关于数据库哪些部分发生漂移的详细信息。 当开发数据库已被手动修改时,可能会显示以下示例输出: Color
枚举缺少预期的变体 RED
,并包含意外的变体 TRANSPARENT
[*] Changed the `Color` enum
[+] Added variant `TRANSPARENT`
[-] Removed variant `RED`
生成新的迁移
假设 Prisma Migrate 没有检测到模式漂移,它会继续从 Prisma 模式更改生成新的迁移。 为了生成新的迁移,Prisma Migrate 会
- 将目标数据库模式计算为当前 Prisma 模式的函数。
- 比较现有迁移历史记录的最终状态和目标模式,并生成从一种状态过渡到另一种状态的步骤。
- 将这些步骤渲染为 SQL 字符串,并将其保存在新的迁移文件中。
- 评估由 SQL 引起的数据丢失,并对此发出警告。
- 将生成的迁移应用于开发数据库(假设您没有指定
--create-only
标志) - 删除影子数据库(通过
shadowDatabaseUrl
配置的影子数据库不会被删除,但在migrate dev
命令开始时会被重置)
手动配置影子数据库
在某些情况下,手动定义应该用作 migrate dev
的影子数据库的连接字符串和数据库名称可能是有意义的(例如,当云托管数据库不允许创建和删除数据库时)。 在这种情况下,您可以
- 创建一个专用的数据库,该数据库应被用作影子数据库
- 将该数据库的连接字符串添加到您的环境变量
SHADOW_DATABASE_URL
(或.env
文件) - 添加读取此环境变量的
shadowDatabaseUrl
字段
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
重要提示:不要为
url
和shadowDatabaseUrl
使用完全相同的值,因为这可能会删除您数据库中的所有数据。
云托管的影子数据库必须手动创建
某些云提供商不允许您使用 SQL 删除和创建数据库。 有些需要通过在线界面创建或删除数据库,有些则真正限制您只能使用 1 个数据库。 如果您在这样的云托管环境中进行开发,则必须
- 创建一个专用的云托管影子数据库
- 将 URL 添加到您的环境变量
SHADOW_DATABASE_URL
- 添加读取此环境变量的
shadowDatabaseUrl
字段
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
重要提示:不要为
url
和shadowDatabaseUrl
使用相同的值。
影子数据库用户权限
为了在使用 migrate dev
时创建和删除影子数据库,Prisma Migrate 当前要求在您的 datasource
中定义的数据库用户具有创建数据库的权限。
数据库 | 数据库用户要求 |
---|---|
SQLite | 无特殊要求。 |
MySQL/MariaDB | 数据库用户必须具有 CREATE, ALTER, DROP, REFERENCES ON *.* 权限 |
PostgreSQL | 用户必须是超级用户或具有 CREATEDB 权限。 请参阅 CREATE ROLE (PostgreSQL 官方文档) |
Microsoft SQL Server | 用户必须是站点管理员或具有 SERVER 安全对象。 请参阅官方文档。 |
如果您在云托管数据库上进行开发并且无法使用这些权限,请参阅:云托管的影子数据库
注意:在 Azure SQL 等数据库上,自动创建影子数据库的功能已被禁用。
如果 Prisma Migrate 无法使用您连接 URL 提供的凭据创建影子数据库,则会抛出以下错误
Error: A migration failed when applied to the shadow database
Database error: Error querying the database: db error: ERROR: permission denied to create database
要解决此错误
- 如果您在本地工作,我们建议您更新数据库用户的权限。
- 如果您正在针对不允许创建和删除数据库的数据库进行开发(出于任何原因),请参阅手动配置影子数据库
- 如果您正在针对云数据库(例如,在 Heroku、Digital Ocean 或 Vercel Postgres 上)进行开发,请参阅:云托管的影子数据库。
- 如果您正在针对云数据库(例如,在 Heroku、Digital Ocean 或 Vercel Postgres 上)进行开发,并且目前处于原型设计阶段,以至于您不关心生成的迁移文件,而只需要将您的 Prisma 模式应用于数据库模式,则可以运行
prisma db push
而不是prisma migrate dev
命令。
重要提示:影子数据库仅在开发环境(特别是对于
prisma migrate dev
命令)中是必需的 - 您无需对您的生产环境进行任何更改。