1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】Alembic とは

1
Posted at

はじめに

FastAPI や SQLAlchemy を使って開発していると、どうしても避けられないのが:

  • テーブルの追加
  • カラムの追加
  • カラム名変更
  • 型変更
  • インデックス追加
  • 制約の追加・削除

これが “野生の ALTER TABLE” で行われると、プロダクトは 確実に崩壊する。

そこで登場するのが Alembic

Alembic は:

  • DBスキーマを「コードとして」バージョン管理する
  • 変更を upgrade/downgrade で自由に行き来できる
  • ステージング・本番・ローカルを常に同じ状態に保つ

という、実務で必須のツール。


1. Alembic の特徴とメリット(実務目線)

1.1 スキーマ変更を「履歴化」できる

すべての変更は revision として蓄積される。

例:

alembic/
  versions/
    20250101_create_user_table.py
    20250103_add_email_column.py

これにより:

  • スキーマ変更の“責任者”と“目的”が明確
  • 過去に戻せる
  • 規模が大きくなっても変更管理が破綻しない

1.2 SQLAlchemy モデルと同期できる(autogenerate)

変更後のモデルと DB の実際を比較し、差分だけを自動生成する:

alembic revision --autogenerate -m "add email"

自動でマイグレーションが生成される。
実務では 8割自動 / 2割手動 が最も安全。


1.3. どの環境でも統一できる

alembic upgrade head

全員が 同じスキーマバージョンになる。
チーム開発での事故率が激減。


1.4. 本番移行が安全

CI/CD で自動化すれば、“本番に勝手に ALTER が走る事故”を防止。


2. Alembic 導入(FastAPI × SQLAlchemy 例)

ディレクトリ構成

project/
  alembic/
    versions/
    env.py
    script.py.mako
  alembic.ini

  app/
    db/
      base.py
      session.py
    models/
      user.py
      item.py

初期化コマンド

alembic init alembic

alembic/alembic.ini が生成される。


env.py – metadata を読み込む(超重要)

# alembic/env.py
from app.db.base import Base  # Base.metadata を使う

target_metadata = Base.metadata

これがないと autogenerate が完全に無反応になる。


3. 初リビジョン作成とマイグレーション

3.1 モデルを書く

# app/models/user.py
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column

class Base(DeclarativeBase):
    pass

class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]
    email: Mapped[str | None]

3.2 Autogenerate 実行

alembic revision --autogenerate -m "create users table"

Alembic が差分を検知し、versions/ にファイル生成。


3.3 マイグレーション適用

alembic upgrade head

DB にテーブルが作成される。


4. よくある変更パターンとマイグレーション例

カラム追加

age: Mapped[int | None]

autogenerate:

op.add_column('users', sa.Column('age', sa.Integer(), nullable=True))

カラム名変更(autogenerateでは気付かない)

SQLAlchemy のモデル変更だけでは検出されず drop/add になる可能性が高いので、

op.alter_column("users", "old_name", new_column_name="new_name")

手動で書く必要あり


インデックス追加

from sqlalchemy import Index

Index("ix_users_email", User.email)

autogenerate は比較的優秀で検出される。


制約(CHECK, UNIQUE, FK)

変更検出がイマイチなので必ずレビュー。


5. Autogenerate が信頼できる部分 / 危険な部分

信頼できる

  • テーブル追加
  • カラム追加
  • 型変更(Integer → String 以外)
  • FK追加/削除
  • Index 追加

危険な部分(レビュー必須)

ケース 理由
Enum の内容変更 DB の Enum は差分判定が難しい
server_default の変更 “変更”が検知されない or 誤検知
Boolean default の変更 DB により挙動が違う
constraint の削除 誤検知 or 未検知
rename column drop/add と誤認する

結論:

autogenerate は 80% 完璧、20% は人間の眼で守る。


6. SQLAlchemy モデルを dataclass にしてはいけない理由

最近「Pydantic v2 = dataclasses ベース」なので誤解が多い。

❌ SQLAlchemy モデルに dataclass を付けると:

  • __init__ が上書きされる
  • default の扱いが壊れる
  • metadata の反映が崩れて autogenerate が混乱

結論:SQLAlchemy モデルは dataclass にしない
(本当に必要なときだけ高度設定)


7. 実務ワークフロー

① モデルを変更する

limit: Mapped[int] = mapped_column(default=10)

② autogenerate 実行

alembic revision --autogenerate -m "add limit to users"

③ 差分をレビュー(必須)

  • DROP が混ざっていないか
  • default が正しいか
  • rename が drop/add になっていないか
  • foreign key が誤検知してないか

④ upgrade で適用

alembic upgrade head

⑤ 本番も upgrade 経由で反映

CI/CD に統合するのがベスト。


8. 実務で起きがちなトラブルと解決方法

❌ autogenerate が何も検出しない

→ ほぼ 100% metadata が読み込まれていない
→ env.py を確認すべき


❌ autogenerate がやたら DROP しまくる

→ モデルの import 順序・重複定義・循環参照が原因


❌ 本番で手動 ALTER したら破壊された

→ Alembic の履歴と DB がズレた
原則:DB に直接触らないこと


❌ downgrade で戻らない

→ downgrade の実装はあくまで“自作”だから当然
→ 本番運用では downgrade を使わないのが一般的


9. プロダクション向け Tips

DB変更は複数ステップで行う

例:大規模 rename や型変換は“安全移行パターン”を使う

  1. 新カラム追加
  2. データ移行
  3. 新カラムに切り替え
  4. 古カラム削除

Alembic 操作は CI/CD に統合する

例:
GitHub Actions で:

alembic upgrade head

本番で絶対にやってはいけない

  • 大量テーブルの rename
  • 大量データの delete
  • autogenerate の無レビュー反映

まとめ

Alembic はただのツールではなく:

  • スキーマの歴史を管理し
  • 誰が見ても理解できる状態を保ち
  • プロダクトの寿命を守る

使えば使うほど 本当の価値がわかるツール

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?