問題の歴史
大規模なプロジェクトに取り組むには、アプリケーションコードと並行してデータベースの構造が進化することが求められます。スキーマのプログラムによるバージョン管理がなければ(テーブル、インデックス、キーの追加、削除、変更)、チームはすぐに非同期状態になり、変更の喪失、マイグレーションの失敗、バグのロールバックや再現が複雑になるリスクが増します。
問題
従来のアプローチであるSQLスクリプトを通じた手動のDB変更は、変更実行の暗黙の順序をもたらし、ロールバックの難しさ、環境間のバージョン不整合(dev、test、prod)を引き起こします。マイグレーションを保存するための共通のツールがなければ、誰が、いつ、なぜスキーマを変更したのかを理解するのが難しくなります。
解決策
この問題には、スキーママイグレーションシステムとデータベースバージョニングのプラクティスが使用されます。ツール(たとえば、Liquibase、Flyway、Alembicなどの異なるDBMS用のもの)を使用することで、スキーマ変更のSQLスクリプトをバージョン管理システム(git)に保存し、マイグレーションの厳格な順序を形成し、すべての環境でのスキーマの更新を自動化できます。
コード例(Flywayによるマイグレーション):
-- V002__add_column_email.sql ALTER TABLE users ADD COLUMN email VARCHAR(255) NOT NULL;
Flywayの統合(たとえばJava用):
Flyway.configure().dataSource(url, user, pass).load().migrate();
重要な特徴:
スキーマの「初期状態」(スナップショット)をマイグレーションの代わりに保存できますか? 一見、「ダンプ」全体はマイグレーションよりもシンプルです。しかし、その場合、ロールバック、中間状態の復元、異なるブランチからの変更のマージに問題が生じます。マイグレーションは、新しい変更を順番に適用することを可能にします。
異なる環境間でマイグレーションを手動で同期する必要がありますか? いいえ、現代のシステムはバージョン管理を尊重し、まだデータベースに存在しないマイグレーションのみを自動的に適用します。重要なのは、手動での同期ではなく、デプロイ時のマイグレーションの自動適用です。
マイグレーションのSQLスクリプトだけで十分ですか、それとも他に何かを保存する必要がありますか? SQLスクリプトに加えてそれらの説明(目的、著者、日付)を保存し、新しい構造変更に対するテストバリデーターを保存するという良いプラクティスがあります。これにより、マイグレーションの品質管理が自動化されます。
プロジェクトでは単純なスキーマダンプと「手動」の変更適用を使用していました。更新を展開した後、クライアントは本番データベースに新しい列の一部が表示されず、インデックスの一部が各更新試行の後に二重化していることに気付きました。
利点:
非常に小さなプロジェクトでは迅速です。
欠点:
サポートが難しい;何が変更され、誰が変更したのかがわからない;ロールバックができない;異なる環境がずれる。
チームはFlywayを統合し、すべての構造変更はコードレビュー付きのマイグレーションで行われました。任意のバージョンのロールバックは数分で完了し、すべての環境でのテストとコントロールが容易になりました。
利点:
自動化、履歴、デプロイ時のバグの可能性が低い。
欠点:
各構造変更を文書化するのに少し時間がかかります。