なぜデータベースデプロイには独自の戦略が必要なのか

アプリケーションのCI/CDパイプラインがうまく機能しているとします。コードの変更はビルド、テスト、そして本番環境へのデプロイまで数分で完了します。チームは1日に何度もリリースをこなし、まったく問題ありません。ところが、誰かが同じパイプラインにデータベースマイグレーションを追加した途端、すべてが崩れ始めます。

大規模なテーブルに対するマイグレーションが45分間実行され、その間テーブルはロックされます。ユーザーはエラーを目にし始め、アプリケーションはリクエストに応答できなくなります。途中でマイグレーションは失敗しますが、一部の行はすでに変更されているため、クリーンにロールバックすることはできません。かつて5分で完了していたパイプラインは1時間かかるようになり、誰も業務時間中に実行しようとはしなくなります。

これはツールの問題ではありません。戦略の問題です。データベースデプロイはアプリケーションデプロイとは根本的に異なる制約の下で動作しており、両者を同じように扱うと、自動化では解決できないリスクが生じます。

アプリケーションデプロイのパターンはそのまま適用できない

アプリケーションデプロイはシンプルで反復可能なパターンに従います。新しいバージョンをビルドし、サーバーにデプロイし、問題が発生したら以前のバージョンにロールバックします。このサイクルは1日に何度も繰り返すことができ、影響は最小限です。古いバージョンはそのまま残り、ファイルも有効です。ロールバックはロードバランサーの設定を以前のリリースに戻すだけです。

データベースデプロイはそうはいきません。マイグレーションを実行するとき、あなたは本番データがすでに存在するデータ構造を変更しています。ロールバックは単純なスイッチの切り替えではありません。追加したカラムを「アンデプロイ」したり、削除したテーブルを注意深く以前の状態に再構築せずに復元したりすることはできません。マイグレーション中に変換されたデータは自動的には元に戻りません。

次のフローチャートは2つのサイクルを対比しています。

flowchart TD subgraph App[アプリケーションデプロイ] A1[ビルド] --> A2[デプロイ] A2 --> A3{成功?} A3 -->|Yes| A4[完了] A3 -->|No| A5[ロールバック: ロードバランサーの設定を戻す] A5 --> A2 end subgraph DB[データベースデプロイ] B1[マイグレーション] --> B2[テーブルロック] B2 --> B3[データ変換] B3 --> B4{成功?} B4 -->|Yes| B5[完了] B4 -->|No| B6[ロールバック: データの再構築] B6 --> B1 end

時間的な要素がこの問題をさらに悪化させます。アプリケーションデプロイは通常、数秒から数分で完了します。一方、大規模なテーブルに対するデータベースマイグレーションは数十分から数時間かかることがあります。その間、テーブルはロックされ、クエリはブロックされ、アプリケーションは部分的または完全に利用できなくなる可能性があります。データベースの変更をアプリケーションワークフローの単なる1ステップとして扱うパイプラインは、これらの現実を無視しています。

パイプラインを分離する理由

このミスマッチに対する最も実用的な対応は、アプリケーションパイプラインとデータベースパイプラインを分離することです。これらは異なるスケジュール、異なるレビュープロセス、そして異なるリスクプロファイルで実行されます。

アプリケーションパイプラインは高速なままです。機能追加、バグ修正、設定変更を1日に何度もリリースし続けます。データベースパイプラインはより慎重なレビューと明示的なスケジューリングのもと、より遅いペースで実行されます。データベースマイグレーションは、それに依存するアプリケーションデプロイの数サイクル前に実行できます。これによりバッファが生まれます。マイグレーションに問題があっても、アプリケーションリリースをブロックせずに修正する時間が確保できます。

この分離は、誰が関与するかも変えます。アプリケーションデプロイは通常、開発チームまたはプラットフォームチームが担当します。データベースデプロイには、スキーマ、データ量、マイグレーションのロック動作を理解しているDBAやチームメンバーの関与が必要になることがよくあります。パイプラインを分離することで、各タイプの変更を誰がレビュー、承認、監視すべきかが明確になります。

後方互換性のあるスキーマ変更でリスクを低減する

データベースデプロイの考え方を変えるもう1つの戦略は、スキーマ変更を後方互換性のあるものにすることです。考え方はシンプルです。古いスキーマと新しいスキーマが一定期間共存できるようにします。これにより、アプリケーションとデータベースの変更を同期させることなく、別々のステップでデプロイできます。

カラム名の変更を考えてみましょう。単純な方法は、1つのマイグレーションでカラム名を変更し、同時にアプリケーションコードを更新することです。何か問題が発生すると、アプリケーションは存在しないカラム名を参照するため、壊れてしまいます。

後方互換性のあるアプローチは異なります。まず、古いカラムを残したまま新しいカラムを追加します。両方のカラムに書き込むようにアプリケーションを更新し、この変更をデプロイします。すべてが正常に動作することを確認したら、古いカラムではなく新しいカラムから読み取るようにアプリケーションを更新し、再度デプロイします。最後に、すべてのコンシューマーが移行した後、別のマイグレーションで古いカラムを削除します。

このプロセスは時間がかかります。複数のデプロイとより多くの調整が必要です。しかし、はるかに安全です。どのステップで問題が発生しても、データベースを不整合な状態にすることなくアプリケーションをロールバックできます。データベースの変更がボトルネックになることは決してありません。

ガバナンスは官僚主義ではなく、保護策である

データベースの変更には、構文チェックを超えたレビュープロセスが必要です。マイグレーションのプルリクエストには、次のような質問への回答を含めるべきです。このマイグレーションはテーブルをロックするか?ロックはどのくらい続くと予想されるか?本番データ量での推定実行時間は?このテーブルから読み取る他のサービスやコンシューマーがいて、影響を受ける可能性はあるか?

これは手続きを増やすことではありません。データベースの変更には、アプリケーションコードの変更にはない影響が伴うことを認識することです。アプリケーションコードのバグは新しいデプロイで修正できます。マイグレーションのバグはデータを破壊したり、ダウンタイムを引き起こしたり、バックアップからの復元を必要としたりする可能性があります。レビュープロセスは、これらのリスクが本番環境に到達する前に捕捉するために存在します。

同じ原則は、誰がマイグレーションを実行できるかにも適用されます。誰もが本番環境に対してスキーマ変更を実行できるべきではありません。これは信頼の問題ではありません。説明責任と、データベースの変更にはデータ量、インデックス、ロック、レプリケーションラグに関する特定の知識が必要であるという現実の問題です。アクセスを制御し、明示的な承認ゲートを備えた独立したパイプラインは、官僚的なハードルではなく、実用的な安全策です。

これがあなたのチームにとって何を意味するか

もしあなたのチームがデータベースマイグレーションをアプリケーションパイプラインの単なる1ステップとして扱っているなら、不必要なリスクを抱えています。解決策はアプリケーションデプロイを遅くすることではありません。データベースデプロイに独自の戦略、独自のパイプライン、独自のレビュープロセスを与えることです。

まずは分離から始めましょう。アプリケーションパイプラインとデータベースパイプラインを独立して実行します。可能な限りスキーマ変更を後方互換性のあるものにします。ロック、タイミング、コンシューマーへの影響に関する適切な質問をするレビュープロセスを構築します。そして、データベースデプロイがアプリケーションデプロイほど高速でカジュアルになることは決してないことを受け入れましょう。それは制限ではありません。何が危険にさらされているかを認識している証なのです。

データベースデプロイ戦略のための実践的チェックリスト

  • アプリケーションパイプラインとデータベースパイプラインは分離されており、異なるスケジュールとレビュープロセスを持つ
  • スキーマ変更は可能な限り後方互換性を持つように設計されている
  • 各マイグレーションには推定実行時間とロック分析が含まれている
  • データベースの変更は、テーブルロックとコンシューマーへの影響に関する明示的なチェックを含むプルリクエストレビューを通過する
  • マイグレーションは本番相当のデータ量を持つステージング環境でテストされる
  • 本番環境でマイグレーションを実行する前に、ロールバック計画が文書化されている

まとめ

データベースデプロイは、既存のパイプラインにマイグレーションツールを追加することで解決できる技術的な問題ではありません。それは戦略の問題であり、異なるタイミング、異なるレビュー基準、異なるリスク許容度を持つ独立したプロセスを設計する必要があります。そのように扱うチームは長期的にはより速くリリースできるようになります。なぜなら、そもそもアプリケーションパイプラインに適合するように設計されていなかったデータベースの変更によってブロックされることがなくなるからです。