跳至主要内容

关于影子数据库

影子数据库是一个第二个,临时的数据库,每次运行 prisma migrate dev 时都会**自动创建和删除**,主要用于**检测**模式漂移或生成的迁移可能导致的数据丢失等问题。

migrate diff 命令 在使用 --from-migrations--to-migrations 与本地 migrations 目录进行差异比较时,也需要影子数据库。

警告

影子数据库在生产环境中**不需要**,并且不会被生产环境相关的命令(例如 prisma migrate resolveprisma migrate deploy)使用。

注意

MongoDB 从未使用影子数据库,因为 migrate dev 不会在那里使用。

影子数据库的工作原理

当您运行 prisma migrate dev 创建新的迁移时,Prisma Migrate 使用影子数据库来

🎨 展开以查看作为卡通解释的影子数据库。

A cartoon that shows how the shadow database works.

检测模式漂移

为了检测开发环境中的漂移,Prisma Migrate

  1. 创建影子数据库的新副本(或者如果影子数据库通过 shadowDatabaseUrl 配置,则执行软重置)。
  2. 在影子数据库中重新运行**当前**存在的迁移历史记录。
  3. **内省**影子数据库以生成 Prisma 模式的“当前状态”。
  4. 将当前迁移历史记录的最终状态与开发数据库进行比较。
  5. 如果当前迁移历史记录的最终状态(通过影子数据库)与开发数据库不匹配(例如,由于手动更改),则报告**模式漂移**

如果 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

  1. 计算作为当前 Prisma 模式函数的目标数据库模式。
  2. 比较现有迁移历史记录的最终状态和目标模式,并生成从一个到另一个的步骤。
  3. 将这些步骤呈现为 SQL 字符串并将其保存在新的迁移文件中。
  4. 评估 SQL 导致的数据丢失并发出警告。
  5. 将生成的迁移应用于开发数据库(假设您未指定 --create-only 标志)
  6. 删除影子数据库(通过 shadowDatabaseUrl 配置的影子数据库不会被删除,但在 migrate dev 命令开始时会被重置)

手动配置影子数据库

在某些情况下,手动定义连接字符串和应用作 migrate dev 的影子数据库的数据库名称可能是有意义的(例如,当在云托管数据库上不允许创建和删除数据库时)。在这种情况下,您可以

  1. 创建一个应用作影子数据库的专用数据库
  2. 将该数据库的连接字符串添加到您的环境变量 SHADOW_DATABASE_URL(或 .env 文件)中
  3. 添加读取此环境变量的 shadowDatabaseUrl 字段
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}

重要:不要对 urlshadowDatabaseUrl 使用完全相同的值,因为这可能会删除数据库中的所有数据。

必须手动创建云托管的影子数据库

一些云提供商不允许您使用 SQL 删除和创建数据库。有些需要通过在线界面创建或删除数据库,有些则确实将您限制为 1 个数据库。如果您在这样的云托管环境中**开发**,则必须

  1. 创建一个专用的云托管影子数据库
  2. 将 URL 添加到您的环境变量 SHADOW_DATABASE_URL
  3. 添加读取此环境变量的 shadowDatabaseUrl 字段
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}

重要:不要对 urlshadowDatabaseUrl 使用相同的值。

影子数据库用户权限

为了在使用 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命令) - 您无需对生产环境进行任何更改。