跳到主要內容

關於影子資料庫

影子資料庫是第二個、暫時性的資料庫,它會在每次您執行 prisma migrate dev自動建立和刪除*,主要用於偵測問題,例如 schema drift 或產生的遷移可能導致的資料遺失。

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.

偵測 Schema Drift

為了在開發中偵測 drift,Prisma Migrate 會

  1. 建立影子資料庫的全新副本(如果影子資料庫是透過 shadowDatabaseUrl 配置,則執行軟重設)
  2. 在影子資料庫中重新執行目前現有的遷移歷史記錄。
  3. 內省影子資料庫以產生 Prisma schema 的「目前狀態」。
  4. 比較目前遷移歷史記錄的最終狀態與開發資料庫。
  5. 如果目前遷移歷史記錄的最終狀態(透過影子資料庫)與開發資料庫不符(例如,由於手動變更),則報告 schema drift

如果 Prisma Migrate 沒有偵測到 schema drift,它會繼續產生新的遷移

注意:影子資料庫不負責檢查遷移檔案是否已被編輯或刪除。這是使用 _prisma_migrations 表格中的 checksum 欄位完成的。

如果 Prisma Migrate 偵測到 schema drift,它會輸出關於資料庫哪些部分發生 drift 的詳細資訊。當開發資料庫已被手動修改時,可能會顯示以下範例輸出: Color 列舉缺少預期的變體 RED,並包含非預期的變體 TRANSPARENT

[*] Changed the `Color` enum
[+] Added variant `TRANSPARENT`
[-] Removed variant `RED`

產生新的遷移

假設 Prisma Migrate 沒有偵測到 schema drift,它會繼續從 Prisma schema 變更產生新的遷移。為了產生新的遷移,Prisma Migrate 會

  1. 將目標資料庫 schema 計算為目前 Prisma schema 的函數。
  2. 比較現有遷移歷史記錄的最終狀態和目標 schema,並產生從一個狀態到另一個狀態的步驟。
  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 ROLEPostgreSQL 官方文件
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 schema 應用於資料庫 schema,則可以執行 prisma db push 而不是 prisma migrate dev 命令。

重要事項:影子資料庫在開發環境中(特別是對於 prisma migrate dev 命令)是必需的 - 您不需要對您的生產環境進行任何變更。