prisma-expand-contract
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePrisma Expand-and-Contract Migrations
Prisma 扩展-收缩模式数据库迁移
Safe, zero-downtime database schema changes with Prisma ORM.
借助Prisma ORM实现安全、零停机的数据库架构变更。
When to Use
适用场景
- Renaming columns or tables in production
- Changing column types (e.g., to
String)Enum - Adding non-nullable columns to tables with existing data
- Splitting or merging tables
- Any schema change that could break running instances during deployment
- 生产环境中重命名字段或表
- 修改字段类型(例如:转为
String)Enum - 向已有数据的表添加非空字段
- 拆分或合并表
- 任何可能在部署期间导致运行中实例崩溃的架构变更
The Pattern
模式说明
Split destructive changes into three phases across multiple deployments:
EXPAND MIGRATE CONTRACT
Add new structure → Copy data, → Remove old structure
update code
Deploy 1 Deploy 2 Deploy 3Why: During deployment, old and new application versions run simultaneously. Direct renames or type changes break old instances immediately.
将破坏性变更拆分为跨多次部署的三个阶段:
EXPAND MIGRATE CONTRACT
Add new structure → Copy data, → Remove old structure
update code
Deploy 1 Deploy 2 Deploy 3原因: 部署期间,新旧版本的应用会同时运行。直接重命名或修改类型会立即导致旧版本实例崩溃。
Core Principles
核心原则
- Never remove in the same deploy as you add - Old code must continue working
- Make changes additive first - Add new columns/tables before removing old
- Code handles both states - During transition, read from new, write to both
- Data migration between deploys - Not during schema migration
- Cleanup is separate - Remove old structures only after all code uses new
- 请勿在添加新结构的同一部署中移除旧结构 - 旧代码必须能继续正常运行
- 优先进行增量变更 - 在移除旧字段/表之前先添加新的
- 代码需兼容两种状态 - 过渡期间,从新结构读取数据,同时向新旧结构写入数据
- 数据迁移需在部署间隙完成 - 不要在架构迁移过程中进行数据迁移
- 清理操作单独进行 - 仅当所有代码都已切换到新结构后,再移除旧结构
Prisma Tools for Renames
Prisma 重命名工具
@map (Column-Level)
@map(字段级)
Maps Prisma field to different database column:
prisma
model User {
displayName String @map("user_name") // Prisma: displayName, DB: user_name
}将Prisma模型字段映射到数据库中的不同字段:
prisma
model User {
displayName String @map("user_name") // Prisma: displayName, 数据库: user_name
}@@map (Table-Level)
@@map(表级)
Maps Prisma model to different database table:
prisma
model Account {
id String @id
@@map("users") // Prisma: Account, DB: users
}Note: / only work for code-level renames. For actual data migration, use full expand-and-contract.
@map@@map将Prisma模型映射到数据库中的不同表:
prisma
model Account {
id String @id
@@map("users") // Prisma: Account, 数据库: users
}注意: /仅适用于代码层面的重命名。如需实际的数据迁移,请使用完整的扩展-收缩模式。
@map@@map@default (Safe Non-Nullable Addition)
@default(安全添加非空字段)
For new columns where a default makes sense:
prisma
model User {
createdAt DateTime @default(now()) // Safe to add directly
isActive Boolean @default(true) // Safe to add directly
}对于可以设置默认值的新字段:
prisma
model User {
createdAt DateTime @default(now()) // 可直接安全添加
isActive Boolean @default(true) // 可直接安全添加
}Common Scenarios
常见场景
| Scenario | Approach |
|---|---|
| Rename column | Add new → backfill → make required → remove old |
| Change type (String→Enum) | Add enum column → backfill mapping → switch reads → remove string |
| Add non-nullable column | Add nullable → backfill → make required |
| Rename table | Create new table → copy data → migrate code → drop old |
| Split table | Add related table → copy data → update code → remove old fields |
For detailed step-by-step implementations, see SCENARIOS.md.
| 场景 | 实现方法 |
|---|---|
| 重命名字段 | 添加新字段 → 回填数据 → 设置为必填 → 移除旧字段 |
| 类型变更(String→Enum) | 添加枚举字段 → 回填映射数据 → 切换读取源 → 移除原字符串字段 |
| 添加非空字段 | 添加可空字段 → 回填数据 → 设置为必填 |
| 重命名表 | 创建新表 → 复制数据 → 迁移代码 → 删除旧表 |
| 拆分表 | 添加关联表 → 复制数据 → 更新代码 → 移除旧字段 |
如需详细的分步实现指南,请查看 SCENARIOS.md。
Anti-Patterns
反模式
Direct Column Rename
直接重命名字段
prisma
// DON'T: Breaks running instances immediately
model User {
displayName String // Was: userName
}prisma
// 请勿这样做:会立即导致运行中实例崩溃
model User {
displayName String // 原字段: userName
}Remove and Add in Same Migration
同一迁移中移除并添加字段
prisma
// DON'T: Old code fails during deployment
model User {
// Removed: userName
displayName String // Added
}prisma
// 请勿这样做:部署期间旧代码会失效
model User {
// 已移除: userName
displayName String // 新增字段
}migrate dev in Production
在生产环境中使用 migrate dev
bash
undefinedbash
// 请勿这样做:可能导致数据丢失
npx prisma migrate dev
// 正确做法:使用 migrate deploy
npx prisma migrate deployDON'T: Can cause data loss
未回填数据就设置为非空
npx prisma migrate dev
prisma
// 请勿这样做:如果存在空值,迁移会失败
model User {
email String // 原类型为 String?
}DO: Use migrate deploy
快速参考
npx prisma migrate deploy
undefinedbash
npx prisma migrate dev --name name # 开发环境:创建并应用迁移
npx prisma migrate deploy # 生产环境:应用待处理的迁移
npx prisma migrate status # 查看迁移状态如需部署检查清单和回滚策略,请查看 CHECKLISTS.md。
Non-Nullable Without Backfill
额外资源
prisma
// DON'T: Migration fails if nulls exist
model User {
email String // Changed from String?
}Quick Reference
—
bash
npx prisma migrate dev --name name # Development: create + apply
npx prisma migrate deploy # Production: apply pending
npx prisma migrate status # View migration statusFor deployment checklists and rollback strategies, see CHECKLISTS.md.
—
Additional Resources
—