Expand-and-Contract パターンを使用したデータ移行
10 分
はじめに
本番環境でデータベーススキーマを変更する際、データの一貫性を確保し、ダウンタイムを回避することが重要です。このガイドでは、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-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
}
1.2. 開発ブランチの作成
変更用の新しいブランチを作成します
git checkout -b create-status-field
2. スキーマの拡張
2.1. 新しいカラムの追加
スキーマを更新して、新しい Status enum とフィールドを追加します
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
3. データの移行
3.1. マイグレーションスクリプトの作成
データ移行用の新しい TypeScript ファイルを作成します
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
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
5. 本番環境へのデプロイ
5.1. デプロイのセットアップ
CI/CD パイプラインに次のコマンドを追加します
npx prisma migrate deploy
5.2. デプロイの監視
ログのエラーを監視し、デプロイ後のアプリケーションの動作を監視します。
トラブルシューティング
よくある問題と解決策
-
デフォルト値の欠落によるマイグレーションの失敗
- 適切なデフォルト値を追加したことを確認してください
- 既存のすべてのレコードを移行できることを確認してください
-
データ損失の防止
- マイグレーションを実行する前に、必ずデータベースをバックアップしてください
- 最初に本番データのコピーでマイグレーションをテストしてください
-
トランザクションのロールバック
- データ移行が失敗した場合、トランザクションは自動的にロールバックされます
- エラーを修正して、マイグレーションを再試行してください
次のステップ
最初の Expand-and-Contract マイグレーションが完了したので、以下を実行できます。
- Prisma Migrate について詳しく学ぶ
- スキーマのプロトタイピング を探索する
- マイグレーションのカスタマイズ を理解する
詳細情報
Prisma とのつながりを維持する
Prisma の旅を続けるには、以下とつながってください。 アクティブなコミュニティ。最新情報を入手し、参加し、他の開発者と協力しましょう。
- X でフォローしてください お知らせ、ライブイベント、役立つヒントをご覧ください。
- Discord に参加してください 質問をしたり、コミュニティと話したり、会話を通じてアクティブなサポートを受けたりできます。
- YouTube でチャンネル登録してください チュートリアル、デモ、ストリームをご覧ください。
- GitHub でエンゲージしてください リポジトリにスターを付けたり、問題を報告したり、問題に貢献したりしてください。