跳到主要內容

修補與熱修復

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

直接修補生產資料庫會導致**模式漂移**:你的資料庫模式已“偏離”了真相來源,並與你的遷移歷史記錄不同步。你可以使用 `prisma migrate resolve` 命令來協調你的遷移歷史記錄,*而無需*使用 `prisma migrate deploy` 命令來移除和重新應用熱修復。

警告

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

透過修補或熱修復協調你的遷移歷史

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

在生產環境中協調你的遷移歷史和資料庫模式

  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 用於對比兩個資料庫模式源,以建立一個將一個模式轉換為第二個模式狀態的遷移。你可以輸出差異摘要或 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 問題 #6485 以獲取更新。

© . This site is unofficial and not affiliated with Prisma Data, Inc.