一般社団法人 全国個人事業主支援協会

COLUMN コラム

  • データベースマイグレーション戦略:ダウンタイムゼロで実現するスキーマ変更

なぜダウンタイムゼロのマイグレーションが求められるのか

現代のWebサービスにおいて、データベーススキーマの変更は避けて通れない作業です。しかし、ユーザー数が増え、24時間365日の稼働が求められる環境では、メンテナンスウィンドウを設けてサービスを停止することは大きなビジネスリスクとなります。私自身、数百万レコードを抱えるテーブルのカラム追加で30分以上のダウンタイムを発生させてしまった苦い経験があります。

ダウンタイムゼロのマイグレーションは、単なる技術的なチャレンジではなく、ビジネス継続性を支える重要な戦略です。本記事では、実務で培ったノウハウをもとに、安全にスキーマ変更を行うための手法を体系的に解説します。

ダウンタイムが発生する典型的なパターン

まず、どのような操作がダウンタイムを引き起こすのかを理解しておきましょう。

  • テーブルロックを伴うALTER TABLE:大規模テーブルへのカラム追加やインデックス作成で、書き込みがブロックされる
  • 破壊的なスキーマ変更:カラムの削除やリネーム、型の変更など、アプリケーションとの互換性が即座に失われる操作
  • データ移行を伴う変更:テーブル分割やデータ正規化など、大量のデータ書き換えが必要な操作
  • 外部キー制約の追加:既存データの整合性チェックに時間がかかり、テーブルがロックされる

これらのパターンを認識した上で、それぞれに対する回避策を持っておくことが重要です。

Expand and Contract パターン

ダウンタイムゼロマイグレーションの基本戦略として最も広く採用されているのが「Expand and Contract(拡張と収縮)」パターンです。

フェーズ1:拡張(Expand)

新しいスキーマ構造を追加しますが、古い構造はそのまま残します。例えば、カラム名を変更したい場合は、新しいカラムを追加するだけにとどめます。この時点ではアプリケーションは旧カラムを使い続けます。

フェーズ2:移行(Migrate)

アプリケーションを更新して、新旧両方のカラムに書き込むようにします。同時に、既存データを旧カラムから新カラムへバックフィルします。この段階ではデュアルライトの状態です。

フェーズ3:収縮(Contract)

全データの移行が完了し、アプリケーションが新カラムのみを使用するように更新した後、旧カラムを削除します。この削除も段階的に行い、まず読み取りを新カラムに切り替え、十分な監視期間を経てから旧カラムを削除します。

このパターンのポイントは、各フェーズが独立してデプロイ可能であることです。問題が発生した場合、任意のフェーズでロールバックできます。

オンラインスキーマ変更ツールの活用

大規模テーブルのスキーマ変更には、専用のオンラインスキーマ変更ツールが有効です。

主要なツールと特徴

  • gh-ost(GitHub Online Schema Transmogrifier):GitHub社が開発したMySQL向けツール。バイナリログを利用してデータを複製し、トリガーを使わないのが特徴。本番環境への負荷を細かく制御できます
  • pt-online-schema-change:Percona Toolkitの一部。トリガーベースでデータを同期するため設定がシンプル。歴史が長く実績が豊富
  • PostgreSQLのCREATE INDEX CONCURRENTLY:PostgreSQLに組み込まれた並行インデックス作成機能。テーブルロックを取らずにインデックスを構築できます

実務では、gh-ostを使って数億レコードのテーブルにカラムを追加した経験がありますが、スロットリング機能のおかげでレプリケーション遅延を1秒以内に抑えながら安全に完了できました。

後方互換性を保つマイグレーション設計

ダウンタイムゼロを実現するには、データベースの変更とアプリケーションのデプロイが同時に行われないことを前提とした設計が必要です。

安全なマイグレーションの原則

  • 追加は安全、削除は危険:カラムやテーブルの追加は基本的に安全。削除は必ずアプリケーション側の対応が先
  • NULLを許容するカラムから始める:新規カラムにはNOT NULL制約を最初から付けない。デフォルト値の設定も慎重に行う
  • デプロイ順序を意識する:スキーマ変更→アプリデプロイの順序で、各ステップが独立して安全であることを確認
  • ロールバック計画を必ず用意する:各マイグレーションステップに対して、逆方向のマイグレーションを準備しておく

段階的リリースとフィーチャーフラグの併用

スキーマ変更を安全に進めるもう一つの強力な手法が、フィーチャーフラグとの併用です。新しいスキーマを使うコードパスをフィーチャーフラグで制御することで、問題発生時にデータベースのロールバックなしにアプリケーション側で即座に切り戻しができます。

具体的には、以下のような流れになります。

  1. 新スキーマをデプロイ(Expandフェーズ)
  2. フィーチャーフラグをOFFにした状態で、新スキーマ対応コードをデプロイ
  3. バックフィルジョブを実行してデータを移行
  4. フィーチャーフラグを段階的にONにして、少数のユーザーから新コードパスを検証
  5. 問題がなければ全ユーザーに展開し、旧スキーマを削除

この手法の利点は、データベースレベルのロールバックという最もリスクの高い操作を回避できます点にあります。

監視と検証の重要性

どんなに慎重にマイグレーションを設計しても、本番環境では予期しない問題が発生する可能性があります。以下の監視ポイントを押さえておきましょう。

  • レプリケーション遅延:マイグレーション中にレプリカの遅延が増加していないか
  • クエリパフォーマンス:スロークエリの増加やレスポンスタイムの悪化がないか
  • ディスクI/O:マイグレーション中のディスク使用率が許容範囲内か
  • アプリケーションエラー率:マイグレーション前後でエラー率に変化がないか

特に大規模なバックフィルジョブを実行する際は、バッチサイズの調整とスロットリングが不可欠です。一度に大量のレコードを更新すると、ロック競合やレプリケーション遅延の原因になります。

まとめ:安全なマイグレーションは文化から

ダウンタイムゼロのマイグレーションは、ツールや手法だけでなく、チーム全体の文化として根付かせることが重要です。コードレビューでマイグレーションの安全性を確認する習慣、本番環境と同等のデータ量でのテスト環境の整備、そしてマイグレーションの実行手順書とロールバック手順書の作成。これらを日常的なプラクティスとすることで、スキーマ変更に対する恐怖心がなくなり、継続的なデータベース改善が可能になります。変更を恐れないために、変更を安全にする仕組みを整えましょう。

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア