用 Alembic 管理 SQLAlchemy Migration 筆記

Posted by Young on 2025-09-12
Estimated Reading Time 3 Minutes
Words 871 In Total

目標:當遷移歷史混亂或想用現有模型重新建立「乾淨」的初始遷移時,安全地重置 Alembic 狀態並升到最新。

TL;DR — 指令清單

1 生成初始 migration

1
alembic revision --autogenerate -m "initial migration"

2 執行 migration(創建表格)

1
alembic upgrade head

3 刪除所有遷移檔案(如已刪除可跳過

1
2
rm -f alembic/versions/*.py
rm -rf alembic/versions/__pycache__

4 清理資料庫版本記錄(Docker 版)

1
docker exec keyword_correction-postgres-1   psql -U keyword -d keyword_correction   -c "DELETE FROM alembic_version;"

非 Docker 版本可用:
psql -h 127.0.0.1 -U keyword -d keyword_correction -c "DELETE FROM alembic_version;"

5 檢查 Alembic 狀態(指定設定檔)

1
2
alembic -c alembic.ini current
# 預期:沒有版本記錄(空白)

6 再次生成「初始遷移」檔案

1
alembic revision --autogenerate -m "initial migration"

7 執行遷移

1
alembic upgrade head

8 確認歷史

1
alembic history

詳細步驟與說明

Step 1–2:先用現有模型嘗試產生與執行初始遷移

確定 migrations/env.py(或 alembic/env.py)內的:

1
2
# 要指向你的 SQLAlchemy Declarative Base
target_metadata = Base.metadata

已設定正確,並能偵測到模型差異。alembic upgrade head 會將 DB 升到最新。

Step 3:刪除舊遷移檔

清空 alembic/versions/,避免舊遷移歷史干擾(務必先備份或在版本控制中操作)。

Step 4:清理 DB 的 Alembic 版本表

alembic_version 通常僅有一列紀錄目前版本。用 DELETE 清空即可。

如果這張表不存在,代表 DB 未受 Alembic 管理,可跳過或稍後用 alembic stamp 對齊。

Step 5:確認狀態

alembic current 應無輸出(表示 DB 目前未標記任何遷移版本)。

Step 6–7:重新產生並執行「初始遷移」

--autogenerate 會根據 target_metadata 與資料庫現況比對產生遷移腳本。請務必審閱遷移檔(欄位型別、索引、約束),再 upgrade head

Step 8:檢視歷史

alembic history 應只顯示你的「初始遷移」與後續新增的遷移(若有)。


注意事項 / 小陷阱

  • 先備份:清遷移與改 DB 前,請先 pg_dump(或備份資料卷),避免不可逆損失。

  • autogenerate 不是全能:對 trigger、部分複雜 constraint 或 server_default 等,可能無法自動偵測,需手動補上。

  • SQLite 例外多:欄位變更常走「建新表 → 搬資料 → 刪舊表」策略;Alembic 會用 batch mode 協助但仍需審閱。

  • 版本標記 vs. 真正遷移:若 DB schema 已手動對齊,只想「告訴 Alembic 目前是最新」,可改用:

    1
    alembic stamp head

    這不會執行任何 SQL,只會寫入版本表。

  • 多人開發分支:若 alembic heads 顯示多個 head,需先 alembic merge -m "merge heads" <revA> <revB> 合併,再 upgrade head

  • 設定檔路徑:多環境時可用 -c path/to/alembic.ini 指定;多 DB 則可用 -n <section> 選擇命名段落。

  • 傳遞自訂參數alembic -x key=value ... 可在 env.pycontext.get_x_argument(as_dictionary=True) 讀取(例如 -x schema=public)。


驗證清單

  • [ ] alembic current 顯示為最新(或你預期的版本)
  • [ ] alembic heads 僅一個 head(或已完成合併)
  • [ ] 重要表格/索引/約束皆已建立
  • [ ] 上線前在 staging 跑過 alembic upgrade head --sql 檢視 SQL(必要時)
  • [ ] PR 內附遷移檔,且已 code review

參考補充指令

  • 顯示詳細歷史:

    1
    alembic history --verbose
  • 顯示指定版本資訊:

    1
    alembic show <rev>
  • 只產出 SQL(不執行):

    1
    2
    alembic upgrade head --sql > upgrade.sql
    alembic downgrade -1 --sql > downgrade.sql

以上流程親測適用:Docker + PostgreSQL(容器名 keyword_correction-postgres-1、DB keyword_correction、使用者 keyword)。依你的環境調整容器名、帳號與資料庫名稱即可。


若您覺得這篇文章對您有幫助,歡迎分享出去讓更多人看到⊂◉‿◉つ~


留言版