跳到主要內容

修補與熱修復

修補或熱修復資料庫涉及直接在生產環境中進行通常時間緊迫的變更。例如,您可能會直接在生產資料庫中新增索引,以解決執行緩慢的查詢問題。

直接修補生產資料庫會導致schema 偏移:您的資料庫 schema 已「偏移」了真理來源,並且與您的遷移歷史記錄不同步。您可以使用 prisma migrate resolve 命令來協調您的遷移歷史記錄,無需移除並使用 prisma migrate deploy 重新套用熱修復。

警告

本指南不適用於 MongoDB
對於 MongoDB,使用 db push 而不是 migrate dev

使用修補或熱修復協調您的遷移歷史記錄

以下情境假設您已在生產環境中進行手動變更,並希望將該變更傳播到您的遷移歷史記錄和其他資料庫。

在生產環境中協調您的遷移歷史記錄和資料庫 schema

  1. 在 schema 中複製您在生產環境中所做的變更 - 例如,將 @@index 新增至特定模型。

  2. 產生新的遷移,並記下完整的遷移名稱,包括時間戳記,該名稱會寫入 CLI:(20210316150542_retroactively_add_index

    npx prisma migrate dev --name retroactively-add-index
    顯示CLI結果
    migrations/
    └─ 20210316150542_retroactively_add_index/
    └─ migration.sql

    Your database is now in sync with your schema.

    ✔ Generated Prisma Client (2.19.0-dev.29) to .\node_modules\@prisma\client in 190ms
  3. 將遷移推送至生產環境,但不執行 migrate deploy。而是將上一步驟中建立的遷移標記為「已套用」,以便 Prisma Migrate 不會嘗試第二次套用您的熱修復

    prisma migrate resolve --applied "20201127134938-retroactively-add-index"

    此命令會將遷移新增至遷移歷史記錄表,而無需執行實際的 SQL。

  4. 針對已修補的其他資料庫重複上一步驟 - 例如,如果您將修補程式套用至預備資料庫。

  5. 將遷移傳播到未修補的其他資料庫 - 例如,透過將遷移提交到原始碼控制,並允許您的 CI/CD 管道將其套用至所有資料庫。

注意:遷移不會套用至已透過 prisma migrate resolve 命令標記為已套用的資料庫。

遷移失敗

遷移可能會在以下情況下失敗

  • 您在執行遷移之前修改了遷移並引入語法錯誤
  • 您將強制性 (NOT NULL) 欄位新增至已包含資料的表格
  • 遷移程序意外停止
  • 資料庫在遷移程序中關閉

_prisma_migrations 表格中的每個遷移都有一個 logs 欄位,用於儲存錯誤。

在生產環境中處理失敗遷移有兩種方法

  • 回滾,選擇性地修正問題,然後重新部署
  • 手動完成遷移步驟並解析遷移

選項 1:將遷移標記為已回滾並重新部署

以下範例示範如何回滾遷移,選擇性地進行變更以修正問題,然後重新部署

  1. 將遷移標記為已回滾 - 這會更新 _prisma_migrations 表格中的遷移記錄,以將其註冊為已回滾,允許再次套用

    prisma migrate resolve --rolled-back "20201127134938_added_bio_index"
  2. 如果遷移已部分執行,您可以選擇

    • 修改遷移以檢查步驟是否已完成(例如:CREATE TABLE ... IF NOT EXISTS

    • 手動還原已完成的步驟(例如,刪除已建立的表格)

    如果您修改遷移,請確保將其複製回原始碼控制,以確保您的生產資料庫狀態完全反映在開發環境中。

  3. 修正失敗遷移的根本原因(如果相關) - 例如,如果遷移由於 SQL 腳本本身的問題而失敗。請確保將任何變更的遷移複製回原始碼控制。

  4. 重新部署遷移

    prisma migrate deploy

選項 2:手動完成遷移並解析為已套用

以下範例示範如何手動完成遷移步驟並將遷移標記為已套用。

  1. 手動完成生產資料庫上的遷移步驟。請確保任何手動步驟與遷移檔案中的步驟完全一致,並將任何變更複製回原始碼控制。

  2. 將遷移解析為已套用 - 這會告知 Prisma Migrate 認為遷移已成功套用

    prisma migrate resolve --applied "20201127134938_my_migration"

使用 migrate diffdb execute 修正失敗的遷移

為了協助修正失敗的遷移,Prisma ORM 提供了以下命令來建立和執行遷移檔案

  • prisma migrate diff,它會比較兩個資料庫 schema 來源,以建立一個遷移,將一個資料庫遷移到第二個資料庫的狀態。您可以輸出差異摘要或 SQL 腳本。腳本可以透過 > file_name.sql 輸出到檔案中,或透過管道傳輸到 db execute --stdin 命令。
  • prisma db execute,它會將 SQL 腳本套用至資料庫,而無需與 Prisma 遷移表格互動。

這些命令在版本 3.9.0 及更高版本(帶有 --preview-feature CLI 標誌)的預覽版中提供,並在版本 3.13.0 及更高版本中全面提供。

本節提供失敗遷移的範例情境,並說明如何使用 migrate diffdb execute 來修正它。

失敗遷移範例

假設您在 schema 中有以下 User 模型,無論是在本機開發環境還是生產環境中

schema.prisma
model User {
id Int @id
name String
}

此時,您的 schema 是同步的,但兩個環境中的資料不同。

然後,您決定變更您的資料模型,新增另一個 Post 模型,並使 User 上的 name 欄位成為唯一的

schema.prisma
model User {
id Int @id
name String @unique
email String?
}

model Post {
id Int @id
title String
}

您使用命令 prisma migrate dev -n Unique 建立名為「Unique」的遷移,該遷移會儲存在您的本機遷移歷史記錄中。在本機開發環境中套用遷移成功,現在是發布到生產環境的時候了。

不幸的是,此遷移只能部分執行。建立 Post 模型並新增 email 欄位成功,但使 name 欄位唯一失敗,並出現以下錯誤

ERROR 1062 (23000): Duplicate entry 'paul' for key 'User_name_key'

這是因為您的生產資料庫中存在非唯一資料(例如,兩個使用者具有相同的名稱)。

您現在需要手動從部分執行的遷移中恢復。在您從失敗狀態恢復之前,無法使用 prisma migrate deploy 進行進一步的遷移。

此時有兩個選項,取決於您決定如何處理非唯一資料

  • 您意識到非唯一資料是有效的,並且您無法繼續當前的開發工作。您想要回滾完整的遷移。若要執行此操作,請參閱向後移動並還原所有變更
  • 資料庫中存在非唯一資料是無意的,您想要修正它。修正後,您想要繼續進行其餘的遷移。若要執行此操作,請參閱向前移動並套用遺失的變更

向後移動並還原所有變更

在這種情況下,您需要建立一個遷移,將您的生產資料庫恢復到上次遷移之前的資料模型狀態。

  • 首先,您需要失敗遷移之前的時間點的遷移歷史記錄。您可以從您的 git 歷史記錄中取得,或在本機刪除遷移歷史記錄中上次失敗遷移的資料夾。

  • 您現在想要將生產環境從目前的失敗狀態恢復到本機遷移歷史記錄中指定的狀態

    • 執行以下 prisma migrate diff 命令

       npx prisma migrate diff \
      --from-url "$DATABASE_URL_PROD" \
      --to-migrations ./prisma/migrations \
      --shadow-database-url $SHADOW_DATABASE_URL \
      --script > backward.sql

      這將建立一個 SQL 腳本檔案,其中包含將生產環境從目前的失敗狀態恢復到遷移歷史記錄定義的目標狀態所需的所有變更。請注意,由於我們正在使用 --to-migrations,因此命令需要影子資料庫

    • 執行以下 prisma db execute 命令

       npx prisma db execute --url "$DATABASE_URL_PROD" --file backward.sql

      這會針對目標資料庫套用 SQL 腳本中的變更,而無需與遷移表格互動。

    • 執行以下 prisma migrate resolve 命令

       npx prisma migrate resolve --rolled-back Unique

      這會將生產環境中遷移表格中名為「Unique」的失敗遷移標記為已回滾。

您的本機遷移歷史記錄現在產生與您的生產資料庫狀態相同的結果。您現在可以再次修改資料模型,以建立適合您對正在處理的功能的新理解(具有非唯一名稱)的遷移。

向前移動並套用遺失的變更

在這種情況下,您需要修正非唯一資料,然後按計劃繼續進行其餘的遷移

  • 嘗試將遷移部署到生產環境的錯誤訊息已告知您 name 欄位中存在重複資料。您需要變更或刪除有問題的列。

  • 繼續套用其餘的失敗遷移,以達到 schema.prisma 檔案中定義的資料模型

    • 執行以下 prisma migrate diff 命令


      npx prisma migrate diff --from-url "$DATABASE_URL_PROD" --to-schema-datamodel schema.prisma --script > forward.sql

      這將建立一個 SQL 腳本檔案,其中包含將生產環境從目前的失敗狀態恢復到 schema.prisma 檔案中定義的目標狀態所需的所有變更。

    • 執行以下 prisma db execute 命令

      npx prisma db execute --url "$DATABASE_URL_PROD" --file forward.sql

      這會針對目標資料庫套用 SQL 腳本中的變更,而無需與遷移表格互動。

    • 執行以下 prisma migrate resolve 命令

      npx prisma migrate resolve --applied Unique

      這會將生產環境中遷移表格中名為「Unique」的失敗遷移標記為已套用。

您的本機遷移歷史記錄現在產生與您的生產環境狀態相同的結果。您現在可以繼續使用已知的 migrate dev /migrate deploy 工作流程。

遷移歷史記錄衝突

資訊

這不適用於 3.12.0 及更高版本。

如果已編輯已套用的遷移,prisma migrate deploy 會發出警告 - 但是,它不會停止遷移程序。若要移除警告,請從原始碼控制還原原始遷移。

Prisma Migrate 和 PgBouncer

如果您嘗試在使用 PgBouncer 進行連線集區的環境中執行 Prisma Migrate 命令,您可能會看到以下錯誤

Error: undefined: Database error
Error querying the database: db error: ERROR: prepared statement "s0" already exists

有關更多資訊和解決方法,請參閱Prisma Migrate 和 PgBouncer 解決方法。請關注 GitHub issue #6485 以取得更新。