テックブログ

DBマイグレーションとは?手作業のALTER TABLEを卒業する基本

DBマイグレーションとは?手作業のALTER TABLEを卒業する基本

DBマイグレーションとは、テーブル作成、カラム追加、インデックス追加などのデータベース構造の変更をSQLファイルなどとして履歴管理し、決められた順序で開発・検証・本番といった各環境へ適用する仕組みです。開発者が環境ごとにALTER TABLEを手作業で実行する方法と比べて、変更の適用漏れ、SQLを実行する順序の間違い、環境ごとのDB構造のずれを減らしやすくなります。Gitと組み合わせれば、アプリケーションコードだけでなく「DBをどう変更したか」もチームで追跡・レビューできます。

1. DBマイグレーションとは

1-1. DBスキーマの変更を履歴として管理する

DBマイグレーションは、データベースのスキーマ変更を「履歴」として残しながら適用する考え方です。現在のテーブル構造だけを見るのではなく、どの変更を順番に適用して現在の状態になったのかを管理します。

アプリケーション開発では、機能追加に伴ってDB構造も変化します。最初はusersテーブルにidnameしかなくても、メールアドレス機能を追加するとemailカラムが必要になるかもしれません。その変更をSQLファイルとして残しておけば、別の開発者や別環境でも同じ変更を再現できます。

例えば「ユーザー登録機能にメールアドレスを追加した」という変更を、アプリコードだけでなくDB変更ファイルとして残します。DBマイグレーションは、DBを手作業で完成形に直すのではなく、変更手順そのものを管理する仕組みだと理解すると分かりやすいです。

1-2. データ移行とは意味が異なる

ここでいうDBマイグレーションは、別のデータベース製品へデータを引っ越す処理だけを意味するものではありません。本記事では主に、アプリケーション開発に伴うDBスキーマの変更管理を指します。

「マイグレーション」という言葉は文脈によって、OracleからPostgreSQLへ移行する、オンプレミスDBをクラウドへ移す、といった意味でも使われます。しかしWebアプリケーション開発では、テーブル追加やカラム変更をバージョン付きで管理する意味で使われることも多くあります。

例えばusersテーブルにemailカラムを追加する作業もDBマイグレーションです。データを別DBへコピーしていなくても、「スキーマをある状態から次の状態へ進める」変更として管理します。

1-3. どのような変更を管理するのか

DBマイグレーションでは、主にデータベース構造に関わる変更を管理します。代表例は、テーブル作成、カラム追加、インデックス追加、制約追加などです。

具体的には、CREATE TABLEALTER TABLECREATE INDEXなどのSQLが対象になります。場合によっては初期データ投入なども管理対象になりますが、まずはスキーマ変更の履歴管理として理解すれば十分です。

例えば次のような変更があります。

ALTER TABLE users
ADD COLUMN email VARCHAR(255);

何をしているのか: 既存のusersテーブルへ、メールアドレスを保存するemailカラムを追加しています。

なぜ必要なのか: アプリケーション側でemailを保存するコードを追加しても、DB側にカラムが存在しなければ正常に動作しません。アプリコードとDB変更をセットで管理する必要があります。

2. 手作業でDBを変更すると何が起きるのか

2-1. ALTER TABLEの実行漏れが発生する

環境ごとに人が手作業でALTER TABLEを実行すると、どこかの環境だけ変更を適用し忘れる可能性があります。環境が増えるほど、この問題は起きやすくなります。

例えば開発者がローカルDBへ次のSQLを実行したとします。

ALTER TABLE users
ADD COLUMN email VARCHAR(255);

開発環境では正常に動作したため、そのままアプリケーションコードをGitへPushしました。しかし検証環境ではSQLを実行し忘れ、本番環境では別の担当者が後日手作業で適用したとします。

このような運用では、「どの環境にどのSQLを実行したか」を人の記憶やチャット履歴に頼ることになります。マイグレーションファイルを使えば、適用すべき変更を履歴として残し、環境ごとに同じ手順を再現しやすくなります。

2-2. SQLを実行する順番を間違える

DB変更には順番が重要な場合があります。複数のSQLを人が手作業で実行すると、順序を間違えてエラーになることがあります。

例えば先にusersテーブルを作成し、その後にemailカラムを追加する必要があるとします。

1. usersテーブルを作成
2. users.emailカラムを追加
3. users.emailへインデックスを追加

このとき、テーブル作成前にカラム追加SQLを実行すれば失敗します。また、環境ごとに適用順序が異なると、DB構造が意図しない状態になる可能性もあります。

マイグレーションでは変更ごとに順序を持たせ、決められた順番で適用します。これにより、「何を先に実行するべきだったか」を担当者が毎回覚えておく必要を減らせます。

2-3. 誰が何を変更したのか分からなくなる

DBへ直接SQLを実行するだけでは、その変更の意図や履歴がソースコードと分離してしまいがちです。後から見たときに「このカラムはいつ、何のために追加されたのか」が分からなくなります。

例えば本番DBにemailカラムがあるものの、Git上にはその変更を示すファイルがない場合、チームメンバーはDBを直接確認しないと変更履歴を把握できません。作業メモやチャットにしか記録がないと、時間がたつほど追跡が難しくなります。

DB変更をSQLファイルとしてGitへ保存すれば、コミット履歴から「誰が追加したか」「どのPull Requestでレビューされたか」「どのアプリ変更とセットだったか」を確認しやすくなります。

3. 開発・検証・本番でDB構造がずれる問題

3-1. 開発環境だけカラムが追加されている

DB変更を手作業で管理すると、開発・検証・本番でスキーマが異なる「環境差異」が発生しやすくなります。アプリケーションコードが同じでも、DB構造が違えば動作結果は変わります。

例えば開発環境だけにemailカラムが追加されている状態を考えます。

開発DB
users
├── id
├── name
└── email

検証DB
users
├── id
└── name

本番DB
users
├── id
└── name

開発者のPCではメールアドレス登録機能が正常に動作します。しかし検証環境へデプロイすると、emailカラムがないためSQLエラーになる可能性があります。

この問題の本質は、アプリケーションコードだけを同じバージョンにしても、DB側が同じ状態とは限らないことです。DB変更にも再現可能な手順が必要です。

3-2. 環境ごとに適用済みの変更が分からなくなる

手作業のDB変更が増えると、「どの環境にどこまで変更済みか」を管理するのが難しくなります。変更が1回だけなら覚えられても、数十回になれば人の記憶には頼れません。

例えば次の3つの変更があるとします。

変更1: usersテーブル作成
変更2: emailカラム追加
変更3: emailへインデックス追加

開発は変更3まで、検証は変更2まで、本番は変更1まで、という状態になっても、記録がなければすぐには把握できません。

マイグレーションツールでは通常、どこまで変更を適用したかをDB側の履歴として管理します。そのため、未適用の変更を判定して順番に進められます。個別ツールの仕組みは異なりますが、「適用済みを記録する」という考え方が重要です。

3-3. アプリとDBの前提がずれると障害につながる

アプリケーションが想定するDB構造と実際のDB構造がずれると、本番障害につながる可能性があります。DB変更はアプリコードとは別物ではなく、アプリを動かすための前提条件です。

例えば次のJavaコードがemailカラムの存在を前提としているとします。

SELECT id, name, email
FROM users;

本番DBにemailがなければ、このSQLは正常に実行できません。アプリケーションのバイナリだけ最新にしても、DBスキーマが古ければ機能は動作しません。

そのためデプロイでは、「アプリケーションのバージョン」と「必要なDBマイグレーション」を一緒に考える必要があります。DBマイグレーションは、アプリとDBの前提をそろえるための仕組みでもあります。

4. マイグレーションファイルで変更を管理する

4-1. DB変更をSQLファイルとして残す

DBマイグレーションでは、実行したいDB変更をSQLファイルとして残します。これにより、手作業のSQLを一度きりの作業ではなく、再現可能な変更手順として扱えます。

例えば次のようなファイルを用意します。

migrations/
├── 001_create_users.sql
└── 002_add_email_to_users.sql

002_add_email_to_users.sqlの中身は、例えば次のようになります。

ALTER TABLE users
ADD COLUMN email VARCHAR(255);

何をしているのか: usersテーブルへemailカラムを追加する変更を、ファイルとして残しています。

なぜ必要なのか: 開発者のPCだけで実行して終わるのではなく、検証・本番にも同じ変更を再現できるようにするためです。

実際のファイル名や命名規則は利用するツールによって異なります。本記事では、重要なのは「DB変更をファイルとして保存し、変更履歴にする」という考え方です。

4-2. 変更を決められた順番で適用する

マイグレーションファイルは、決められた順番で適用します。これにより、依存関係のあるDB変更を正しい順序で再現できます。

例えば次の流れです。

001_create_users.sql
        ↓
usersテーブル作成
        ↓
002_add_email_to_users.sql
        ↓
emailカラム追加

開発・検証・本番のすべてで同じ順番を使えば、「検証だけ先にemailを追加した」「本番ではテーブル作成SQLを飛ばした」といった状態を防ぎやすくなります。

ただし、マイグレーションツールを使えばSQL実行が必ず安全になるわけではありません。処理時間の長いALTER TABLEや大量データへ影響する変更などは、適用タイミングや影響範囲を別途確認する必要があります。

4-3. 適用済みの変更を管理する

マイグレーションでは、どの変更まで適用済みなのかを管理することも重要です。同じSQLを毎回すべて実行するのではなく、未適用の変更だけを進めます。

基本的な変更フローは次のように考えられます。

Gitにあるマイグレーション

001_create_users.sql      → 適用済み
002_add_email_to_users.sql → 適用済み
003_add_index.sql          → 未適用
             ↓
      マイグレーション実行
             ↓
      003だけを適用
             ↓
      適用済みとして記録

この仕組みによって、各環境を同じ順番で最新状態へ進められます。FlywayやLiquibaseなどのツールは、このようなマイグレーション管理を支援します。

5. DB変更をGitで管理する

5-1. アプリケーションコードとDB変更を一緒に管理する

DBマイグレーションファイルは、アプリケーションコードと同じGitリポジトリで管理すると変更の関係を追いやすくなります。

例えばメールアドレス登録機能を追加するとき、Javaコードだけでなくemailカラム追加SQLも同じブランチへ含めます。

project/
├── src/
│   └── ...
└── migrations/
    ├── 001_create_users.sql
    └── 002_add_email_to_users.sql

1つのPull Requestに、

- Userクラスへemailを追加
- 登録画面へemail入力欄を追加
- usersテーブルへemailカラムを追加

という変更をまとめられます。

Gitが保存するのはマイグレーションファイルであって、実際のDBそのものではありません。usersテーブルに保存されているユーザーデータまでGit管理されるわけではない点に注意してください。

5-2. Pull Requestでスキーマ変更をレビューする

マイグレーションファイルをGit管理すると、DB変更もPull Requestのレビュー対象にできます。手作業で本番へSQLを投入するだけの場合より、変更内容をチームで確認しやすくなります。

例えばレビュー時に次のSQLが確認できます。

ALTER TABLE users
ADD COLUMN email VARCHAR(255);

レビュー担当者は「カラム名は適切か」「型は適切か」「NULLを許可する設計でよいか」「既存アプリへの影響はないか」といった点を確認できます。

DB変更はアプリケーションコード以上に慎重な確認が必要になることもあります。マイグレーションファイル化することで、SQLをチームの通常の開発フローへ組み込みやすくなります。

5-3. 変更履歴からDB構造の変化を追跡する

Git管理されたマイグレーションを見ると、DB構造がどのように変わってきたかを後から追跡できます。現在のCREATE TABLE文だけでは分からない経緯も残せます。

例えば履歴が次のようになっていれば、

001_create_users.sql
002_add_email_to_users.sql
003_add_users_email_index.sql

「最初はidとnameだけだった」「後からemailが必要になった」「さらに検索性能のためインデックスを追加した」という変化を理解できます。

Gitのコミット履歴やPull Requestと組み合わせれば、その変更がどの機能追加と関係していたかも追跡できます。これは障害調査や新しいメンバーへの引き継ぎでも役立ちます。

6. DBマイグレーションを導入するときの注意点

6-1. マイグレーションは安全性を自動保証するものではない

DBマイグレーションを導入しても、SQLそのものが自動的に安全になるわけではありません。間違ったSQLをマイグレーションファイルへ書けば、その間違いも再現されます。

例えば誤って必要なカラムを削除するSQLを書いた場合、マイグレーションツールはそのSQLの業務上の正しさまで判断してくれるとは限りません。

そのため、Pull Requestでのレビュー、検証環境での動作確認、バックアップや復旧手順の確認などは引き続き必要です。マイグレーションは「変更を管理・再現しやすくする仕組み」であり、「安全性を自動保証する仕組み」ではありません。

6-2. 本番適用方法をチームで決める

本番DBへマイグレーションをいつ、誰が、どの方法で適用するかは、チームでルールを決める必要があります。開発者が自由に本番DBへ自動適用すればよいとは限りません。

例えば、小規模なシステムではアプリケーションデプロイ時に自動実行する構成もあります。一方、重要なDBではCI/CDの専用ステップとして実行し、承認後に進める運用もあります。

重要なのは、自動か手動かという二択ではなく、失敗時の影響、権限管理、監査、停止時間などを考慮してチームに合った方法を決めることです。

6-3. 適用済みの変更を安易に書き換えない

すでに他の環境へ適用済みのマイグレーションファイルは、安易に書き換えないことが基本です。過去の変更履歴と実際のDB状態がずれる可能性があるためです。

例えば002_add_email_to_users.sqlを開発・検証・本番へ適用した後で、中身を別のSQLへ変更すると、新しく環境を作ったときと既存環境で結果が変わる可能性があります。

新しい変更が必要なら、過去のファイルを編集するのではなく、新しいマイグレーションとして追加する方法を基本にします。具体的な扱いは利用するツールやチームルールにも従ってください。

7. まとめ

7-1. 手作業とマイグレーション管理の違い

DBマイグレーションは、DB構造の変更を履歴として管理し、同じ変更を決められた順序で各環境へ適用するための考え方です。ALTER TABLEそのものを否定する仕組みではなく、そのSQLを「誰かの手作業」ではなく「管理された変更」として扱います。

手作業とマイグレーション管理を比較すると、次のようになります。

項目手作業でSQL実行マイグレーション管理
DB変更の保存メモやチャットに残る場合があるSQLファイルなどで履歴化
適用順序人が判断決められた順番で管理
適用漏れ起こりやすい未適用変更を把握しやすい
環境差異発生しやすい同じ変更を再現しやすい
Git管理SQLが残らない場合もあるDB変更ファイルを管理できる
Pull RequestDB変更が見えにくいSQLもレビュー対象にできる
変更履歴人の記憶に依存しやすいファイルとGit履歴から追跡可能
SQLの安全性開発者が確認マイグレーションでも別途確認が必要

DBマイグレーションの目的は、単にSQL実行を自動化することではありません。アプリケーションコードと同じように、DBスキーマの変更にも履歴と再現性を持たせることが重要です。

7-2. DB変更を管理するときのチェックリスト

DB変更を管理するときは、「SQLを書けるか」だけでなく、その変更を他の環境でも同じように再現できるかを確認します。

特に複数人・複数環境で開発する場合は、手作業だけで変更を共有するのではなく、ファイルとGitを使って履歴を残すことが重要です。

実装・運用時には、次の項目を確認してください。

  • DBマイグレーションをスキーマ変更の履歴管理として理解している
  • データベース製品間の引っ越しだけを意味するものと誤解していない
  • テーブル作成やカラム追加をファイルとして残している
  • ALTER TABLEを各環境で手作業だけに頼っていない
  • 開発・検証・本番で同じ変更順序を再現できる
  • どの変更まで適用済みか把握できる
  • アプリコードとDB変更をセットで管理している
  • マイグレーションファイルをGitへ保存している
  • GitがDBそのものを保存するわけではないと理解している
  • DB内の実データまでGit管理されると誤解していない
  • Pull RequestでSQLもレビューしている
  • 適用済みマイグレーションを安易に書き換えていない
  • 本番への適用方法をチームで決めている
  • マイグレーションを使ってもSQLレビューが必要だと理解している
  • CI/CDから実行する場合も権限や失敗時の対応を決めている

DBマイグレーションを導入する価値は、「手動SQLをゼロにすること」そのものではありません。DB変更をアプリケーションコードと同じ開発プロセスへ組み込み、誰が見ても「何を、どの順番で変更したのか」を追跡できる状態を作ることにあります。

8. 参考リンク

この記事では、次の公式資料を参考情報として挙げています。