使用擴展與收縮(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. 執行遷移
- 更新您的 DATABASE_URL 以指向正式環境資料庫
- 執行遷移腳本
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. 監控部署
觀察日誌中是否有任何錯誤,並在部署後監控應用程式的行為。
疑難排解
常見問題與解決方案
-
遷移因缺少預設值而失敗
- 確保您已新增適當的預設值
- 檢查所有現有記錄是否皆可被遷移
-
資料遺失預防
- 執行遷移前,請務必備份您的資料庫
- 先在正式環境資料的副本上測試遷移
-
交易回滾(Transaction rollback)
- 如果資料遷移失敗,交易將會自動回滾
- 修復任何錯誤並重新嘗試遷移
後續步驟
現在您已完成第一次擴展與收縮的遷移,您可以
- 進一步了解 Prisma Migrate
- 探索 架構原型設計
- 理解 自訂遷移
更多資訊
與 Prisma 保持聯繫
透過以下方式與我們聯繫,繼續您的 Prisma 旅程: 我們的活躍社群。保持資訊靈通、參與其中,並與其他開發者合作
- 在 X 上關注我們 以獲取公告、現場活動和實用技巧。
- 加入我們的 Discord 提出問題、與社群對話,並透過對話獲得積極支援。
- 在 YouTube 上訂閱 查看教學、演示和直播。
- 在 GitHub 上交流 透過為存放庫加星標、報告問題或為 issue 做出貢獻。