データベースマイグレーション

英語名 Database Migration
読み方 データベース マイグレーション
難易度
所要時間 導入に1〜3日
提唱者 Ruby on Rails(Active Record Migrations)が普及に貢献
目次

ひとことで言うと
#

データベースのスキーマ変更(テーブル追加・カラム変更など)をコードとしてバージョン管理し、順序通りに適用・巻き戻しできるようにする手法。「本番DBに手動でALTER TABLE」という危険な運用から脱却する。

押さえておきたい用語
#

押さえておきたい用語
マイグレーションファイル(Migration File)
スキーマ変更の内容を記述したバージョン管理されたファイルのこと。タイムスタンプ+説明の命名規則(例: 20260309_add_email_to_users.sqlで順序を保証する。
UP / DOWN
マイグレーションの**適用(UP)と巻き戻し(DOWN)**のペアのこと。UPでカラム追加→DOWNでカラム削除のように、すべての変更にロールバック手順を用意する。
オンラインDDL(Online DDL)
大規模テーブルのスキーマ変更をテーブルロックなしで実行するツールや手法のこと。gh-ost、pt-online-schema-changeなどが代表例。
ゼロダウンタイムマイグレーション
サービスを停止せずにスキーマ変更を完了させる手法のこと。通常2〜3段階のデプロイに分けて、アプリの変更とDB変更を段階的に適用する。

データベースマイグレーションの全体像
#

データベースマイグレーション:安全なスキーマ変更のフロー
マイグレーションファイルタイムスタンプ + 説明で命名1ファイル1変更の原則UP: スキーマ変更を適用DOWN: 変更を巻き戻しコードレビューの対象にする安全なパターンカラム追加: NULLableで追加カラム削除: 参照除去→次リリースで削除テーブルリネーム: 新→コピー→切替→旧削除大量データ変更: バッチ処理で少しずつ破壊的変更は最低2段階デプロイに分けるCI/CDパイプラインへの統合CI: テスト環境でマイグレーションが正常適用されるか検証CD: アプリデプロイ前にマイグレーションを自動実行マイグレーションは必ずアプリデプロイより先に実行する
ゼロダウンタイムマイグレーションの流れ
1
ツール導入
Flyway/Alembic等でマイグレーション基盤を構築
2
運用ルール策定
命名規則・UP/DOWN必須・レビュー対象化
3
安全パターン適用
2段階デプロイで破壊的変更を安全に実施
CI/CD統合
パイプラインで自動適用・検証を実現

こんな悩みに効く
#

  • 本番DBのスキーマが開発環境と微妙にずれていて、デプロイ時にエラーが出る
  • 誰がいつどんなスキーマ変更をしたか追跡できない
  • スキーマ変更を手動で本番に適用しており、ミスが怖い

基本の使い方
#

ステップ1: マイグレーションツールを導入する

プロジェクトの技術スタックに合ったマイグレーションツールを選択する。

  • Flyway: Java系プロジェクトで定番。SQLベースでシンプル
  • Liquibase: XML/YAML/JSONでスキーマ変更を定義。DB非依存
  • Alembic: Python(SQLAlchemy)向け
  • golang-migrate: Go向け。SQLファイルベース
  • 各フレームワーク内蔵: Rails Migrations、Django Migrations、Laravel Migrations

ポイント: SQLベースのツールはDBに依存しない記述が難しいが、チームが理解しやすい。

ステップ2: マイグレーションファイルの運用ルールを決める

チームで一貫したルールを定める。

  • ファイル命名: タイムスタンプ + 説明(例: 20260309120000_add_email_to_users.sql
  • 1ファイル1変更: 1つのマイグレーションには関連する変更だけを含める
  • ロールバック: UPとDOWNの両方を必ず書く(戻せない変更は例外として明記)
  • レビュー: マイグレーションファイルもコードレビューの対象にする

ポイント: マイグレーションの順序は変更しない。途中に挿入すると環境間で不整合が起きる。

ステップ3: 安全なスキーマ変更パターンを使う

本番稼働中のDBに対してダウンタイムなしで変更を適用するパターンを身につける。

  • カラム追加: NULLableで追加 → アプリケーション対応 → NOT NULLに変更
  • カラム削除: アプリケーションから参照を除去 → 次のリリースでカラム削除
  • テーブルリネーム: 新テーブル作成 → データコピー → アプリ切り替え → 旧テーブル削除
  • 大量データの変更: バッチ処理で少しずつ変更(ロック競合を防ぐ)

ポイント: 破壊的な変更は最低2段階のデプロイに分ける。アプリの変更とDB変更を同時にやらない。

ステップ4: CI/CDパイプラインに組み込む

マイグレーションを自動化パイプラインに統合する。

  • CIで: マイグレーションがテスト環境で正常に適用されることを検証
  • CD(デプロイ時)で: アプリケーションデプロイ前にマイグレーションを自動実行
  • ロールバック計画: 失敗時に前バージョンに戻す手順を事前に用意

ポイント: マイグレーションは必ずアプリのデプロイより先に実行する。順序を逆にするとアプリがスキーマ不整合で落ちる。

具体例
#

例1:emailカラムを3段階デプロイでゼロダウンタイム追加する

状況: usersテーブル(300万行)にemailカラムを追加したい。本番は24時間稼働でダウンタイム不可。

Phase 1 - カラム追加(マイグレーション): ALTER TABLE users ADD COLUMN email VARCHAR(255) NULL; NULLableで追加するので、既存のコードに影響なし。

Phase 2 - アプリケーション対応: 新コードはemailカラムの読み書きに対応。既存レコードのemailはNULLでもエラーにならない設計。バックグラウンドジョブで既存ユーザーのemail移行を実行。

Phase 3 - 制約追加(全データ移行完了後): ALTER TABLE users ALTER COLUMN email SET NOT NULL; + UNIQUE制約を追加。

結果: ダウンタイムゼロでスキーマ変更完了。各フェーズの間隔は1〜2日空けて安全を確認。

例2:5億行のテーブルにオンラインDDLでインデックスを追加する

問題: ordersテーブル(5億行、200GB)に新しいインデックスを追加したい。通常のCREATE INDEXではテーブルロックが推定4時間かかり、その間注文処理が停止する。

対策: gh-ost(GitHub Online Schema Tool)を使用。元テーブルのコピーを作成し、binlogを使ってリアルタイムに差分を同期。コピー完了後にアトミックにテーブルを入れ替え。

実行: gh-ost --alter="ADD INDEX idx_user_date(user_id, created_at)" を実行。バックグラウンドで6時間かかったが、その間のサービスへの影響はCPU使用率+5%程度。ダウンタイムはゼロ

結果: オンラインDDLの導入により、大規模テーブルのスキーマ変更が「営業時間中でも安全」に実行可能になった。

例3:マイグレーション失敗を自動ロールバックでリカバリする

状況: ステージング環境でのマイグレーションは成功したが、本番環境でデータ量の違いからタイムアウトで失敗。デプロイパイプラインが中断。

自動ロールバックの仕組み:

  1. マイグレーション実行前にスナップショットを自動取得
  2. マイグレーション実行(タイムアウト制限: 30分
  3. 失敗時に自動でDOWNスクリプトを実行
  4. DOWNも失敗した場合はスナップショットからリストア
  5. Slackに即座にアラートを送信

結果: マイグレーション失敗から5分以内に自動ロールバックが完了。以前は手動対応で平均45分かかっていた障害対応が90%短縮

やりがちな失敗パターン
#

  1. ロールバックスクリプトを書かない — 問題が発生した時に手動で戻すのは危険でミスが起きやすい。すべてのマイグレーションにDOWNスクリプトを用意する
  2. 大テーブルにALTER TABLEを一発で実行する — 数億行のテーブルへのALTER TABLEはロックがかかり、サービスが止まる。オンラインDDLツール(gh-ost、pt-online-schema-change)を使う
  3. マイグレーションとアプリデプロイを同時にする — スキーマ変更とアプリの変更を同じデプロイで実施すると、失敗時の切り戻しが複雑になる。マイグレーションは独立したステップとして実行する
  4. テスト環境でのマイグレーション検証を省略する — 本番で初めて実行して失敗するケースが多い。CIで自動的にマイグレーションの適用を検証する仕組みを組み込む

まとめ
#

データベースマイグレーションは 「DBの変更履歴をコードで管理する」 という、現代のソフトウェア開発に不可欠なプラクティス。手動のALTER TABLEから脱却し、バージョン管理されたマイグレーションファイルで安全にスキーマを進化させよう。本番環境では「2段階デプロイ」と 「オンラインDDL」 を組み合わせて、ゼロダウンタイムを実現することが成功の鍵だ。