Erdmates Logo
Erdmates
ブログ一覧へ
マイグレーションデータベースDevOpsゼロダウンタイム

データベースマイグレーション戦略:ダウンタイムなしで本番DBを安全に変更する

ブルーグリーンデプロイメントからエクスパンド/コントラクトパターンまで、本番環境でのスキーマ変更を安全に行うための実践的な戦略を解説します。

2026年4月3日10 分で読めます

マイグレーションが怖い理由

「本番DBのスキーマ変更は怖い」と感じている開発者は多いでしょう。テーブルのカラム追加程度であればリスクは低いですが、カラムの削除、リネーム、大規模なデータ移行が必要な変更では、アプリケーションの停止や最悪の場合データ損失のリスクがあります。しかし適切な戦略を用いることで、ほとんどのマイグレーションをダウンタイムなしで実施できます。

基本原則:後方互換性を維持する

最も重要な原則は「デプロイ中も古いバージョンのアプリと新しいバージョンのアプリが同時に動作できる状態を維持する」ことです。ブルーグリーンデプロイやカナリアリリースでは、新旧バージョンが同時に実行される期間があるため、データベーススキーマは両バージョンに対応している必要があります。

パターン1:エクスパンド/コントラクト(Expand/Contract)

カラムのリネームやテーブル構造の大幅変更に有効なパターンです。3段階に分けて変更を行います。

-- 例:users.full_name を first_name + last_name に分割する変更

-- === Phase 1: EXPAND(拡張)===
-- 新しいカラムを追加(古いカラムはまだ残す)
ALTER TABLE users ADD COLUMN first_name VARCHAR(100);
ALTER TABLE users ADD COLUMN last_name VARCHAR(100);

-- 既存データを移行
UPDATE users SET
  first_name = SPLIT_PART(full_name, ' ', 1),
  last_name  = SPLIT_PART(full_name, ' ', 2)
WHERE first_name IS NULL;

-- アプリは full_name と first_name/last_name の両方に書き込む

-- === Phase 2: MIGRATE(移行)===
-- 新バージョンのアプリをデプロイ(first_name/last_nameを使用)
-- 旧バージョンのアプリを徐々に停止

-- === Phase 3: CONTRACT(縮小)===
-- 古いカラムを削除(全アプリが新バージョンになった後)
ALTER TABLE users DROP COLUMN full_name;

パターン2:段階的なインデックス作成

大規模テーブルへのインデックス追加はテーブルロックを引き起こす場合があります。PostgreSQLのCREATE INDEX CONCURRENTLYを使用することでロックを回避できます。

-- ❌ 通常のインデックス作成(テーブルをロック)
CREATE INDEX idx_orders_created_at ON orders(created_at);

-- ✅ 並行インデックス作成(テーブルロックなし)
-- ※ 時間は長くかかるが、本番環境への影響を最小化
CREATE INDEX CONCURRENTLY idx_orders_created_at ON orders(created_at);

-- インデックス作成の進捗確認
SELECT phase, blocks_done, blocks_total,
       ROUND(100.0 * blocks_done / NULLIF(blocks_total, 0), 1) AS progress_pct
FROM pg_stat_progress_create_index
WHERE relid = 'orders'::regclass;

パターン3:大量データの分割マイグレーション

数百万件のデータを一度に更新するとロングトランザクションが発生し、レプリケーション遅延やロック問題を引き起こします。バッチ処理で分割して実行しましょう。

-- ❌ 悪い例:数百万件を一度に更新
UPDATE orders SET status = 'legacy_pending' WHERE status = 'pending';

-- ✅ 良い例:バッチ処理で分割実行
DO $$
DECLARE
  batch_size INT := 10000;
  updated_count INT;
BEGIN
  LOOP
    UPDATE orders SET status = 'legacy_pending'
    WHERE id IN (
      SELECT id FROM orders
      WHERE status = 'pending'
      LIMIT batch_size
      FOR UPDATE SKIP LOCKED
    );

    GET DIAGNOSTICS updated_count = ROW_COUNT;
    EXIT WHEN updated_count = 0;

    -- レプリケーションに追いつく時間を与える
    PERFORM pg_sleep(0.1);
    RAISE NOTICE 'Updated % rows', updated_count;
  END LOOP;
END $$;

パターン4:フィーチャーフラグとの組み合わせ

スキーマ変更とアプリコードの変更を完全に分離するため、フィーチャーフラグを活用します。新しいカラムやテーブルはスキーマに追加しつつ、アプリ側ではフラグが有効になるまで使用しません。

-- マイグレーション管理テーブル
CREATE TABLE schema_migrations (
  version     VARCHAR(14) PRIMARY KEY,  -- タイムスタンプ形式:20260403120000
  description TEXT NOT NULL,
  applied_at  TIMESTAMP DEFAULT NOW(),
  rollback_sql TEXT  -- ロールバック手順を記録
);

INSERT INTO schema_migrations(version, description, rollback_sql)
VALUES (
  '20260403120000',
  'Add first_name and last_name columns to users',
  'ALTER TABLE users DROP COLUMN first_name, DROP COLUMN last_name'
);

Erdmatesでマイグレーション計画を立てる

スキーマ変更を実施する前に、ErdmatesでERDを最新化し「Before/After」を視覚的に確認することをお勧めします。変更の影響範囲(どのテーブルがどのように変わるか)をERDで整理しておくことで、チーム全体がマイグレーション計画を共有でき、手順のレビューもスムーズになります。

まとめ

データベースマイグレーションは計画的に行えば、ダウンタイムなしで安全に実施できます。エクスパンド/コントラクトパターン、並行インデックス作成、バッチ処理の3つの手法を使い分けることで、ほとんどのシナリオに対応できます。最も重要なのは、一度のデプロイで大きな変更を行うのではなく、小さな変更を段階的に積み重ねていく姿勢です。

Erdmatesで今すぐ始めましょう

AI搭載ERDエディタでデータベース設計を始めましょう。無料でご利用いただけます。

無料デモを試す無料で始める

関連記事

bigint・UUID v4・UUID v7:主キーの選び方(PostgreSQL 18 の uuidv7() 対応)

bigint・UUID v4・UUID v7 の主キーの長所と短所を比べ、PostgreSQL 18 に入った uuidv7() で変わった点と、状況別の選び方を整理します。

AIエージェントが読むデータベース:MCP時代のスキーマ設計原則

AIエージェントがMCPを通じてデータベースに直接接続するケースが増えています。エージェントがスキーマを誤って解釈しないように名前・コメント・制約を設計し、権限を安全に分ける方法を整理します。

PostgreSQL 19プレビュー:スキーマ設計と運用に影響する変更点(ベータ4時点)

正式リリースを控えたPostgreSQL 19の変更点のうち、テーブル設計・マイグレーション・運用に直接影響するものを公式リリースノート(ベータ4)に基づいて整理します。ベータで取り下げられた機能や、アップグレード前に確認すべき動作の変更もあわせて見ていきます。

Erdmates Logo
Erdmates

自然言語でデータベースを設計し、AI駆動ERDエディターでチームとリアルタイムでコラボレーション。

サービス

  • 機能紹介
  • 料金プラン
  • デモ
  • SQL→ERD変換

リソース

  • ブログ
  • ヘルプ
  • お問い合わせ

法的事項

  • 利用規約
  • プライバシーポリシー
  • 第三者提供
会社名: Produx|代表者: 최정회
住所: 강원특별자치도 원주시 솔우물2길 4-1 (무실동)
メール: master@erdmates.com
個人情報管理責任者: 최정회|ホスティングサービス提供者: Amazon Web Services

© 2026 Produx. All rights reserved.