跳至主要內容

使用擴展與收縮(expand and contract)模式遷移資料

10 分鐘

簡介

在正式環境中對資料庫架構(Schema)進行更改時,確保資料一致性並避免停機至關重要。本指南將展示如何使用「擴展與收縮」(expand and contract)模式,安全地在欄位之間遷移資料。我們將通過一個實際案例,演示如何在保留現有資料的情況下,將布林值(boolean)欄位替換為列舉(enum)欄位。

先決條件

在開始本指南之前,請確保您擁有:

  • 已安裝 Node.js(版本 18 或更高)
  • 一個擁有現有架構的 Prisma ORM 專案
  • 一個受支援的資料庫(PostgreSQL, MySQL, SQLite, SQL Server 等)
  • 擁有開發環境與正式環境資料庫的存取權限
  • 對 Git 分支管理有基本理解
  • 對 TypeScript 有基本熟悉度

1. 設定您的環境

1.1. 檢視初始架構

從包含 Post 模型的基本架構開始

generator client {
provider = "prisma-client"
output = "./generated/prisma"
}

datasource db {
provider = "postgresql"
}

model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
}

1.2. 設定 Prisma

在專案根目錄建立一個包含以下內容的 prisma.config.ts 檔案:

prisma.config.ts
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config';

export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
},
datasource: {
url: env('DATABASE_URL'),
},
});
注意

您需要安裝所需的套件。如果尚未安裝,請使用您的套件管理器進行安裝

npm install prisma @types/pg --save-dev
npm install @prisma/client @prisma/adapter-pg pg dotenv
資訊

如果您使用的是不同的資料庫提供者(MySQL、SQL Server、SQLite),請安裝相應的驅動程式適配器套件,而不是 @prisma/adapter-pg。如需更多資訊,請參閱資料庫驅動程式

:::

1.3. 建立開發分支

為您的變更建立一個新的分支

git checkout -b create-status-field

2. 擴展架構

2.1. 新增欄位

更新您的架構以新增 Status 列舉與欄位

model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean? @default(false)
status Status @default(Unknown)
}

enum Status {
Unknown
Draft
InProgress
InReview
Published
}

2.2. 建立遷移

產生遷移檔案

npx prisma migrate dev --name add-status-column

接著生成 Prisma Client

npx prisma generate

3. 遷移資料

3.1. 建立遷移腳本

為資料遷移建立一個新的 TypeScript 檔案

import { PrismaClient } from '../generated/prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'
import 'dotenv/config'

const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL,
})

const prisma = new PrismaClient({
adapter,
})

async function main() {
await prisma.$transaction(async (tx) => {
const posts = await tx.post.findMany()
for (const post of posts) {
await tx.post.update({
where: { id: post.id },
data: {
status: post.published ? 'Published' : 'Unknown',
},
})
}
})
}

main()
.catch(async (e) => {
console.error(e)
process.exit(1)
})
.finally(async () => await prisma.$disconnect())

3.2. 設定遷移腳本

將遷移腳本新增至您的 package.json

{
"scripts": {
"data-migration:add-status-column": "tsx ./prisma/migrations/<migration-timestamp>/data-migration.ts"
}
}

3.3. 執行遷移

  1. 更新您的 DATABASE_URL 以指向正式環境資料庫
  2. 執行遷移腳本
npm run data-migration:add-status-column

4. 收縮架構

4.1. 建立清理分支

為移除舊欄位建立一個新的分支

git checkout -b drop-published-column

4.2. 移除舊欄位

更新您的架構以移除 published 欄位

model Post {
id Int @id @default(autoincrement())
title String
content String?
status Status @default(Unknown)
}

enum Status {
Draft
InProgress
InReview
Published
}

4.3. 產生清理遷移

建立並執行最終的遷移

npx prisma migrate dev --name drop-published-column

接著生成 Prisma Client

npx prisma generate

5. 部署至正式環境

5.1. 設定部署

將以下指令新增至您的 CI/CD 管線

npx prisma migrate deploy

5.2. 監控部署

觀察日誌中是否有任何錯誤,並在部署後監控應用程式的行為。

疑難排解

常見問題與解決方案

  1. 遷移因缺少預設值而失敗

    • 確保您已新增適當的預設值
    • 檢查所有現有記錄是否皆可被遷移
  2. 資料遺失預防

    • 執行遷移前,請務必備份您的資料庫
    • 先在正式環境資料的副本上測試遷移
  3. 交易回滾(Transaction rollback)

    • 如果資料遷移失敗,交易將會自動回滾
    • 修復任何錯誤並重新嘗試遷移

後續步驟

現在您已完成第一次擴展與收縮的遷移,您可以

更多資訊


與 Prisma 保持聯繫

透過以下方式與我們聯繫,繼續您的 Prisma 旅程: 我們的活躍社群。保持資訊靈通、參與其中,並與其他開發者合作

我們衷心感謝您的參與,並期待您成為我們社群的一份子!

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