マイグレーションってどういう意味?flask db migrateで使う時に理解できるように解説
FlaskでWebアプリを作っていると、あるタイミングで flask db migrate というコマンドに出会うことがあります。
migrate(マイグレート)って何?
と思ったことはありませんか?
マイグレート/マイグレーションとは、ざっくり言うと データベースの構造変更を記録して、あとから安全に反映する仕組み です。
この記事では、プログラミング初心者向けに、マイグレーションの意味から、Flaskでよく使う flask db migrate の役割までわかりやすく解説します。
マイグレーションとは何か¶
まずは、マイグレーションという言葉の意味から整理しましょう。
ITの世界では、マイグレーションという言葉はいくつかの意味で使われます。システム移行、データ移行、環境移行など、文脈によって少し意味が変わります。
一般的な意味は移行¶
migrationは、英語で移動や移住という意味を持つ言葉です。
ITでは、古いシステムから新しいシステムへ移す、古い環境から新しい環境へ移す、といった意味で使われます。
たとえば、古いサーバーから新しいサーバーへアプリを移すこともマイグレーションと呼ばれます。
データベースを別の種類に移すことも、広い意味ではマイグレーションです。
Flaskで使うマイグレーションはDB構造の変更管理¶
一方、Flaskで flask db migrate と言うときのマイグレーションは、主にデータベースの構造変更を管理する意味で使われます。
ここでいう構造とは、テーブル、カラム、型、制約などのことです。
たとえば、ユーザー情報を保存するテーブルに、あとからメールアドレスのカラムを追加したいとします。
このとき、データベースを直接手で変更するのではなく、変更内容をマイグレーションファイルとして記録します。
そして、そのファイルをもとにデータベースへ反映します。
この流れを使うことで、いつ、どんな変更をしたのかを追いやすくなります。
なぜマイグレーションが必要なのか¶
ここで疑問が出てくるかもしれません。
データベースの構造を変えたいなら、直接テーブルを変更すればいいのではないか。そう思うのも自然です。
データベースはアプリの土台だから¶
Webアプリでは、データベースがとても重要です。
ユーザー情報、投稿内容、商品データ、注文履歴など、大切なデータが保存されています。
もし、テーブル構造を適当に変えてしまうと、アプリが動かなくなったり、データを失ったりする可能性があります。
たとえば、ユーザーテーブルに name しかなかった状態から、あとで email を追加する場面を考えます。
開発者Aの環境ではemailカラムがある。でも、開発者Bの環境ではまだない。本番環境にもない。
このような状態になると、同じコードなのに環境によって動いたり動かなかったりします。
変更履歴を残すために必要¶
マイグレーションの大きな役割は、データベース構造の変更履歴を残すことです。
コードはGitで管理できますよね。
同じように、データベースの構造変更もファイルとして管理しておくと、チーム開発や本番反映がかなり楽になります。
エンジニア歴10年の経験でも、マイグレーションがきちんと管理されているプロジェクトは安心感があります。
逆に、誰かが手作業でデータベースを変えていて、変更履歴が残っていないプロジェクトはかなり怖いです。あとから何が正しい状態なのかわからなくなるからです。
Flaskでよく使うflask db migrateとは¶
ここからは、Flaskで出てくる flask db migrate の意味を見ていきましょう。
Flaskでは、Flask-Migrateという拡張機能を使うと、SQLAlchemyのモデル変更をもとにマイグレーションを扱いやすくなります。Flask-Migrateは、Alembicを使ってFlaskアプリのSQLAlchemyデータベースマイグレーションを扱う拡張機能です。
flask db migrateは変更ファイルを作るコマンド¶
flask db migrate は、データベースを直接変更するコマンドではありません。
正確には、モデル定義と現在のデータベースの状態を比べて、変更内容をマイグレーションファイルとして作成するコマンドです。
たとえば、次のようなUserモデルがあるとします。
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
ここに、メールアドレスを追加したいとします。
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
email = db.Column(db.String(120), nullable=True)
この状態で、次のコマンドを実行します。
flask db migrate -m "add email to user"
すると、emailカラムを追加するためのマイグレーションファイルが作られます。
この時点では、まだ実際のデータベースにemailカラムが追加されたわけではありません。
flask db upgradeで実際に反映する¶
作成されたマイグレーションファイルを実際のデータベースに反映するのが、flask db upgrade です。
flask db upgrade
初心者のうちは、ここを混同しやすいです。
flask db migrate は変更案を作る。flask db upgrade はその変更を実際に反映する。
この違いを押さえるだけで、マイグレーションの理解はかなり進みます。
マイグレーションの流れを整理しよう¶
ここで、Flaskでマイグレーションを使う流れを表で整理します。
実際の開発では、だいたい次のような順番で作業します。
| 手順 | コマンドや作業 | 何をしているか |
|---|---|---|
| 1 | モデルを変更する | Pythonコード上でテーブル構造を変える |
| 2 | flask db migrate |
変更内容をマイグレーションファイルにする |
| 3 | ファイルを確認する | 意図した変更になっているか見る |
| 4 | flask db upgrade |
実際のデータベースに反映する |
| 5 | 動作確認する | アプリが正しく動くか確認する |
この表を見ると、migrate と upgrade が別の役割だとわかります。
特に大事なのは、マイグレーションファイルを確認することです。
自動生成されたからといって、必ず完璧とは限りません。
初心者が混乱しやすいポイント¶
マイグレーションは便利ですが、初心者がつまずきやすいポイントもあります。
ここを先に知っておくと、エラーが出たときに焦りにくくなります。
migrateしたのにDBが変わっていない¶
よくあるのが、flask db migrate を実行したのに、データベースの構造が変わっていないというケースです。
これは正常です。
flask db migrate は、変更ファイルを作るだけです。実際にデータベースへ反映するには flask db upgrade が必要です。
つまり、migrateだけで止まっている状態は、設計図を作っただけで工事していない状態に近いです。
モデルを変更していないと差分が出ない¶
次に多いのが、migrateしても何も変更が検出されないケースです。
Flask-Migrateは、基本的にSQLAlchemyのモデル定義を見て差分を作ります。
そのため、モデルを変更していなければ、マイグレーションファイルに書く差分もありません。
たとえば、HTMLやPythonの処理だけを変えても、テーブル構造が変わっていなければDBマイグレーションは不要です。
自動生成を信じすぎると危ない¶
flask db migrate は便利ですが、万能ではありません。
Alembicの自動生成機能は、データベースの現在の構造とアプリ側のメタデータを比較して、候補となるマイグレーションを生成します。ただし、意図した変更になっているかは人間が確認する必要があります。
たとえば、カラム名を変更しただけなのに、古いカラムを削除して新しいカラムを追加するような内容になることがあります。
この場合、データが消える可能性があります。
だから、生成されたマイグレーションファイルは必ず見ましょう。
flask db migrateでよく見るファイル¶
flask db migrate を使うと、プロジェクト内にマイグレーション関連のファイルが作られます。
最初は知らないファイルが増えて驚くかもしれません。
migrationsフォルダとは¶
Flask-Migrateを初期化すると、migrations というフォルダが作られます。
この中に、マイグレーションの設定や、変更履歴のファイルが保存されます。
migrations/
versions/
123abc_add_email_to_user.py
versions フォルダの中にあるPythonファイルが、実際の変更内容を持つマイグレーションファイルです。
このファイルには、主に upgrade() と downgrade() という関数が入っています。
upgradeとdowngradeの意味¶
upgrade() は、データベースを新しい状態に進める処理です。
たとえば、emailカラムを追加する処理が書かれます。
一方、downgrade() は、前の状態に戻す処理です。
たとえば、追加したemailカラムを削除する処理が書かれます。
初心者のうちは、まずupgradeが前へ進む、downgradeが戻る、と覚えておけば大丈夫です。
具体例で理解するマイグレーション¶
ここで、もう少し具体的な例で見てみましょう。
ユーザー登録機能を作っていて、最初は名前だけ保存していたとします。
最初のモデル¶
最初のUserモデルは次のような形です。
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
この状態では、ユーザーの名前だけを保存できます。
しかし、あとからログイン機能を追加したくなり、メールアドレスも必要になりました。
emailカラムを追加する¶
そこで、モデルにemailを追加します。
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
email = db.Column(db.String(120), nullable=True)
この変更をしただけでは、Pythonコード上のモデルが変わっただけです。
実際のデータベースには、まだemailカラムはありません。
そこで、次のコマンドを使います。
flask db migrate -m "add email column to user"
マイグレーションファイルが作られたら、中身を確認します。
問題なければ、次に反映します。
flask db upgrade
これで、実際のデータベースにemailカラムが追加されます。
マイグレーションはGitに似ている¶
初心者に説明するとき、私はよくマイグレーションをGitにたとえます。
Gitはコードの変更履歴を管理しますよね。
マイグレーションは、データベース構造の変更履歴を管理するものだと考えると理解しやすいです。
コードだけではDBの状態は変わらない¶
Gitでコードを管理していても、データベースのテーブル構造は自動では変わりません。
モデルのコードを変更してGitにコミットしても、本番DBにカラムが増えるわけではありません。
その橋渡しをするのがマイグレーションです。
モデルの変更をマイグレーションファイルにして、それをupgradeで反映する。
この流れをチーム全員が共有できると、開発環境や本番環境の差を減らせます。
履歴があると戻しやすい¶
変更履歴があると、何か問題が起きたときに原因を追いやすくなります。
どのタイミングでカラムが追加されたのか。どの変更でテーブルが作られたのか。マイグレーションファイルを見ると、かなり追跡しやすくなります。
もちろん、本番データベースでは簡単に戻せないこともあります。
それでも、履歴があるかないかで安心感は大きく違います。
実務でマイグレーションを扱うときの注意点¶
ここからは、エンジニア歴10年の視点で、実務で気をつけていることを紹介します。
初心者のうちから知っておくと、あとでかなり役立ちます。
本番DBに反映する前に確認する¶
マイグレーションは、データベースの構造を変える操作です。
本番環境で実行する前には、必ず内容を確認します。
特に、カラム削除、テーブル削除、型変更は注意が必要です。
これらはデータ消失につながる可能性があります。学習用のアプリなら失敗してもやり直せますが、本番データでは簡単に戻せません。
マイグレーションファイルを読めるようになる¶
初心者のうちは、生成されたファイルを見るのが怖いかもしれません。
でも、少しずつでいいので読めるようになると強いです。
op.add_column ならカラム追加、op.drop_column ならカラム削除、op.create_table ならテーブル作成です。
すべてを完璧に理解しなくても、危険そうな操作に気づけるだけで十分価値があります。
バックアップを取る¶
本番データベースにマイグレーションを当てる前は、バックアップが大切です。
実務では、万が一のために戻せる状態を用意してから作業します。
個人開発でも、大事なデータが入っているならバックアップを取る習慣を持ちましょう。
これは地味ですが、本当に大切です。
初心者がまず覚えるべきコマンド¶
最後に、Flask-Migrateでよく使うコマンドを整理します。
最初から全部を覚える必要はありません。まずは、init、migrate、upgradeの3つを押さえましょう。
| コマンド | 役割 | 初心者向けのイメージ |
|---|---|---|
flask db init |
マイグレーション環境を作る | 管理用フォルダを準備する |
flask db migrate |
変更ファイルを作る | DB変更の設計図を作る |
flask db upgrade |
DBへ反映する | 設計図どおりに工事する |
flask db downgrade |
前の状態へ戻す | 1つ前の状態に戻す |
flask db history |
履歴を見る | 変更の流れを確認する |
flask db current |
現在の状態を見る | 今どのバージョンか確認する |
この中でも、初心者が一番混同しやすいのは migrate と upgrade です。
migrate はファイル作成。upgrade は実際に反映。ここを何度も確認しましょう。
【関連記事】Pythonからデータベースを操作するsqlite3の使い方を解説
まとめ¶
マイグレーションとは、データベースの構造変更を履歴として管理し、安全に反映するための仕組みです。
Flaskで flask db migrate を使う場合は、SQLAlchemyのモデル変更をもとにマイグレーションファイルを作ります。
ただし、flask db migrate だけでは実際のデータベースは変わりません。
実際に反映するには、flask db upgrade を実行する必要があります。
初心者のうちは、migrateは設計図を作る、upgradeは工事をする、と考えると理解しやすいです。
そして、生成されたマイグレーションファイルは必ず確認しましょう。
マイグレーションは最初こそ難しく感じますが、Webアプリ開発ではとても大切な考え方です。
データベースはアプリの土台です。だからこそ、変更をなんとなく手作業で行うのではなく、履歴として残し、必要な環境に同じように反映できるようにしておきましょう。
ここまでお読みいただきありがとうございました。