LASSIC Media らしくメディア
ゼロダウンタイムDBスキーマ移行を外注で進める
LASSIC IT事業部|元請(プライムベンダー)としてシステム保守・運用を受託
この記事のポイント
- サービスを止めずにデータベースのスキーマを変更することが難しい理由を、ロックとアプリケーションの互換性の観点から整理します。
- expand-contract(拡張・契約)パターンとオンラインDDLツールという2つの基本的な考え方を紹介します。
- 外注でゼロダウンタイム移行を進める際の委託範囲・発注準備で確認すべき論点を示します。
目次
ゼロダウンタイムDBスキーマ移行とは何か
ゼロダウンタイムDBスキーマ移行とは、稼働中のサービスを停止させずに、テーブル構造(カラムの追加・変更・削除や型変更、大規模なデータ移行)を無停止で反映させる開発・運用の手法を指します。カラム追加のような一見単純な変更でも、テーブルのロックやアプリケーションとの整合性次第でサービス影響が生じるため、段階的な移行設計が必要になります*1。
ゼロダウンタイム移行が扱う対象は、カラムの追加・削除・型変更(例:文字列型から数値型への変更)、テーブル分割、大規模なデータ移行(数百万〜数億行規模のバックフィル)など多岐にわたります。共通するのは「スキーマの切り替えとアプリケーションのデプロイを同時に完了させることができない」という制約です*2。この制約を前提に段階を分けて進める設計が、ゼロダウンタイム移行の核心になります。
ALTER文のロックとアプリ互換性が難しさの本質
ゼロダウンタイムでのスキーマ変更が難しい理由は大きく2つに分けられます。第一に、ALTER TABLE文の実行がテーブルロックや大規模な書き換えを伴う場合があることです。第二に、アプリケーションのデプロイとスキーマ変更を完全に同時実行することはできず、新旧コードとDBが一時的に混在する期間が生まれることです。
ALTER文が引き起こすロックとテーブル書き換え
MySQLのInnoDBやPostgreSQLでは、変更の種類によってALTER文の挙動が異なります。カラムの追加やインデックスの作成が既存の全行を書き換える処理になる場合、テーブル全体のロック、あるいはロックしない場合でも長時間の内部コピー処理が発生し、その間のクエリ性能に影響が及ぶことがあります。GitHubが自社のオンラインスキーマ変更ツール「gh-ost」を開発した動機も、大規模テーブルに対する既存ツールの制約(トリガーの負荷やレプリケーションへの影響)を回避するためでした*3。
アプリとDBを同時に切り替えられないという制約
Webサービスのデプロイは通常、複数台のサーバーへ順次リリースするローリングデプロイの形を取ります。この間、旧バージョンのアプリケーションと新バージョンのアプリケーションが同一のデータベースに同時にアクセスする時間帯が発生します。ソフトウェア設計の議論では、この非互換な変更を段階的に進める手法として「Parallel Change(拡張・契約)」パターンが知られており、新旧両方のインターフェースを一時的に共存させることでリスクを下げるとされています*4。DBスキーマの変更も同じ考え方が当てはまり、旧アプリと新アプリのどちらが読み書きしても破綻しない中間状態を経由する設計が求められます。
expand-contract(拡張・契約)パターンの3段階
expand-contract(拡張・契約)パターンは、インターフェースやスキーマの非互換な変更を、後方互換性を保った複数段階に分割して進める手法です*4。DBスキーマ移行に適用する場合、一般に以下の3段階で整理されます。
拡張(Expand)— 新旧を両対応させる
最初の段階では、新しいスキーマ要素(新カラム・新テーブル)を追加し、既存のスキーマは変更・削除しません。アプリケーションは引き続き旧スキーマのみを参照でき、この時点でのデプロイは既存の挙動に影響を与えません。
移行(Migrate)— 両対応の期間を経て段階的に置き換える
次に、アプリケーションを新旧両方のスキーマに対応させ、必要に応じて新旧両方へ書き込む「ダブルライト」を行いながら、既存データを新スキーマへ反映する「バックフィル」を進めます。この期間中はロールバックが可能な状態を維持し、整合性を確認しながら段階的に読み取り元を新スキーマへ切り替えます。
契約(Contract)— 旧スキーマと旧コードを撤去する
すべてのクライアント(アプリケーションの全インスタンス)が新スキーマへの移行を終え、整合性の検証が完了した段階で、旧カラムや旧テーブル、旧スキーマ参照のコードを削除します。この段階を急ぐと、想定していなかった旧コードの参照が残っていた場合に障害の原因となるため、十分な観察期間を設けることが実務上の要点になります。
オンラインDDLツール — gh-ostとpt-online-schema-change
MySQL環境では、大規模テーブルに対するスキーマ変更を無停止で行うための専用ツールが複数存在します。代表的なものがGitHub製の「gh-ost」と、Percona製の「pt-online-schema-change」です。どちらも「新しい構造のテーブルを別途作成し、データを段階的にコピーしたうえで最後に入れ替える」という共通の設計思想を持ちますが、変更の追跡方式が異なります*3*5。
pt-online-schema-change — トリガーで変更を追跡
pt-online-schema-change(Percona Toolkitに含まれるツール)は、元テーブルと同じ構造の空のコピーテーブルを作成してALTERを適用し、元テーブルへのINSERT/UPDATE/DELETEをコピーテーブルへ反映するトリガーを設置します*5。データは小さなチャンク単位で段階的にコピーされ、完了後にRENAME TABLEでテーブルを原子的に入れ替えます。公式ドキュメントは、既存のトリガーとの併用ができないこと、外部キー制約がある場合は交換後の参照更新が必要になること、レプリカの遅延を検知して処理を一時停止する仕組みがあることを明記しています*5。実行には`–execute`オプションが必須で、事前のドキュメント確認とバックアップの検証が前提とされています*5。
gh-ost — バイナリログでトリガーレスに追跡
gh-ostは「GitHub’s Online Schema Transmogrifier」の略で、GitHubが自社の大規模MySQL環境向けに開発したツールです*3。pt-online-schema-changeと同様にゴーストテーブルへ段階的にデータをコピーする方式を取りますが、変更点の追跡にトリガーを使わず、MySQLのバイナリログ(binlog)ストリームを読み取って非同期にゴーストテーブルへ適用する点が特徴です*3。GitHubはこの設計により、マスターDBへの追加負荷を分離できるほか、マイグレーション処理を動的に一時停止・再開・制御できるようになったとしています*3。レプリカでのテスト機能や、カットオーバー(テーブル入れ替え)タイミングの制御機能も備えています*3。
PostgreSQL環境での考え方
PostgreSQLの場合、カラム追加や一部の型変更はMySQLに比べてロック時間が短く済む操作が多い一方、テーブル全体の書き換えを伴う変更や大規模なインデックス作成では、無停止運用のための個別の設計判断が必要です。いずれのRDBMSであっても「どの変更が軽量な操作で、どの変更がテーブル全体の書き換えを要するか」を事前に切り分けたうえで、後述するバックフィルの設計と組み合わせることが実務上の共通論点になります。
バックフィルとダブルライトの設計論点
expand-contractパターンやオンラインDDLツールを実務に落とし込む際、工数がかかりやすいのが「移行期間中のデータ整合性をどう保つか」という設計です。ここでは代表的な2つの論点を整理します。
バックフィル — 大量データの後追い反映をどう分割するか
既存データを新スキーマへ反映するバックフィル処理は、対象データが大規模な場合、一度に実行すると本番DBへの負荷やロック競合を招きます。小さなバッチ単位に分割し、本番トラフィックの状況を見ながら実行間隔を調整する設計が必要です。バックフィルの途中で処理が中断した場合に再開可能な設計(べき等性の担保)も欠かせません。
ダブルライト — 新旧両方への書き込みで生じる不整合をどう防ぐか
移行期間中にアプリケーションが新旧両方のスキーマへ書き込む「ダブルライト」を行う場合、一方の書き込みが失敗したときの扱い(両方失敗させるか、どちらかを優先するか)を事前に設計しておく必要があります。書き込みの順序や失敗時の扱いを曖昧にしたまま進めると、切替後の検証段階で新旧データの不一致が発覚し、契約段階に進めなくなることがあります。
リリース手順・ロールバック設計との整合
ゼロダウンタイム移行は、DBスキーマの変更だけを切り出して検討しても完結しません。アプリケーションのリリース手順、監視体制、ロールバック手順と一体で設計する必要があります。
デプロイ順序とロールバック可能性
expand段階のリリースは既存の挙動を変えないため相対的にリスクが低い一方、migrate段階では新旧コードが混在する時間が長くなるほど、ロールバックの複雑さが増します。ロールバックする際に「新スキーマへの書き込みだけを止めて旧スキーマの状態に戻せるか」を事前に検証しておくことが、移行判断の重要な分岐点になります。
監視すべき指標
移行期間中は、通常の可用性指標(レイテンシ・エラー率)に加えて、新旧データの整合性検証(不一致件数)やバックフィルの進捗(残件数)を監視対象に加える必要があります。オンラインDDLツールを使う場合は、レプリケーション遅延やロック待ちの発生状況も合わせて監視します*5。契約段階へ進む判断は、これらの指標が一定期間安定していることを確認したうえで行います。
内製で進める場合に必要となる知識領域
expand-contract設計・対象RDBMSのロック挙動・オンラインDDLツールの運用経験・アプリケーション側のダブルライト実装・監視設計を、それぞれ独立に理解した担当者が必要です。移行対象のテーブル規模やアプリケーションの構成によって難易度が変わるため、着手前に対象テーブルの行数・参照箇所数・関連バッチ処理の有無を棚卸しし、どの段階に何人日を要するかを見積もる工程が欠かせません。
外注で進める場合の委託範囲と発注準備
ゼロダウンタイムDBスキーマ移行を外部パートナーへ委託する場合、委託範囲を「設計」「実装」「移行実行・監視」のどこまでとするかを事前に整理しておくと、見積もりの精度と後工程の手戻りを抑えられます。
委託範囲の切り分け方
移行方式の設計(expand-contractの段階分けやオンラインDDLツールの選定)、アプリケーション側のダブルライト・バックフィル処理の実装、実際の移行実行と監視・カットオーバー判断は、それぞれ異なるスキルセットを要します。委託先に依頼する範囲を「設計のみ」「設計+実装」「実行・運用まで一貫」のいずれにするかで、契約形態や必要なコミュニケーション頻度が変わります。
発注前に準備しておく情報
発注準備の段階では、対象テーブルのスキーマ定義・行数規模・参照しているアプリケーションやバッチ処理の一覧・許容できるダウンタイムの有無・既存の監視体制を整理しておくと、委託先が移行方式(expand-contractの段階分け、あるいはオンラインDDLツールの適用可否)を具体的に提案しやすくなります。ロールバック方針や契約段階に進む判断基準についても、発注側と委託先の間で事前にすり合わせておくことが、移行完了後の想定外のトラブルを避けるうえで重要です。
失敗コストを踏まえた判断
スキーマ移行を計画不足のまま進めると、移行期間中の不整合や、契約段階での旧コード参照の見落としが障害につながる可能性があります。移行方式の検証や監視設計を省略して進めることは、本番環境での予期しないロックやデータ不整合のリスクを高めるため、事前検証の工数を確保したうえで着手することが望まれます。
まとめ:ゼロダウンタイム移行を任せる判断軸
本稿では、サービスを止めずにDBスキーマを変更するための考え方を整理しました。要点を3つに集約すると次の通りです。第一に、ALTER文のロックとアプリ・DBの同時切替不能という制約が難しさの本質であること。第二に、expand-contractパターンとオンラインDDLツール(gh-ost・pt-online-schema-change)という2つの手法が、それぞれ異なる層(アプリ設計とDB実行)でこの制約に対応していること。第三に、外注する場合は設計・実装・実行監視のどこまでを委託するかを事前に切り分け、対象テーブルの棚卸しとロールバック方針のすり合わせを発注前に済ませておくことが、移行の成否を左右するという点です。
よくある質問
ゼロダウンタイムのスキーマ移行にはどのくらいの期間がかかりますか。
対象テーブルの行数規模、変更内容(カラム追加か型変更か)、アプリケーションの参照箇所数によって大きく変わります。expand-contractパターンでは移行段階(migrate)を一定期間継続して整合性を確認する必要があるため、単純なカラム追加のみの変更よりも設計・検証を含めた工数が必要になります。具体的な期間は対象システムごとの見積もりが前提となります。
MySQLとPostgreSQLで無停止移行のアプローチは異なりますか。
アプリケーション側のexpand-contract設計という考え方は共通ですが、RDBMS側の実装は異なります。MySQLではgh-ostやpt-online-schema-changeのようなゴーストテーブル方式のツールが広く使われています*3*5。PostgreSQLでは変更の種類ごとにロック挙動が異なるため、個別に軽量な操作かどうかを見極める設計が必要です。
外注する場合、DB移行の実行作業まで任せることはできますか。
設計のみの委託から、ダブルライトやバックフィル処理の実装、実際の移行実行・監視までを含めた一貫委託まで、範囲を分けて依頼することが可能です。委託範囲によって契約形態や必要なやり取りの頻度が変わるため、発注前に対象範囲を明確にしておくことが大切です。
移行の途中で問題が起きた場合、元に戻すことはできますか。
expand段階やmigrate段階の初期であれば、新スキーマへの書き込みを止めて旧スキーマの状態に戻す設計が可能な場合が多くあります。ただし契約(contract)段階で旧カラムや旧コードをすでに削除している場合は、ロールバックの難易度が上がります。ロールバック可能な範囲をどこまでとするかを、移行計画の段階で決めておく必要があります。
著者:テレリモ総研編集部 鈴木 亮佑
ご不明な点はお問い合わせフォームからもご連絡いただけます。
- *1 出典:Percona「pt-online-schema-change — Percona Toolkit Documentation」(https://docs.percona.com/percona-toolkit/pt-online-schema-change.html)
- *2 出典:Martin Fowler「ParallelChange」Danilo Sato(2014年)(https://martinfowler.com/bliki/ParallelChange.html)
- *3 出典:GitHub「gh-ost – GitHub’s Online Schema Transmogrifier」(https://github.com/github/gh-ost)
- *4 出典:Martin Fowler「ParallelChange」Danilo Sato(2014年)(https://martinfowler.com/bliki/ParallelChange.html)
- *5 出典:Percona「pt-online-schema-change — Percona Toolkit Documentation」(https://docs.percona.com/percona-toolkit/pt-online-schema-change.html)