Python中實現(xiàn)數(shù)據庫遷移的輕量級方案詳解
先說問題
項目上線之后,數(shù)據庫改動是最容易出事的環(huán)節(jié)。
加一個字段、改一個索引、新建一張表——聽起來很小的事,實際操作中經常踩坑:
- 本地改了,測試環(huán)境忘了改
- 測試改了,生產環(huán)境漏了一條 ALTER
- 多人協(xié)作,不知道哪條 SQL 執(zhí)行過、哪條沒執(zhí)行
- 出了問題想回溯,根本不知道數(shù)據庫當時是什么狀態(tài)
為什么不直接用 Alembic
Alembic 是 Python 生態(tài)里最成熟的數(shù)據庫遷移工具,和 SQLAlchemy 深度集成,功能完整。但用過的人都知道,它有一定的上手門檻:
- 需要理解
env.py、alembic.ini、版本鏈等概念 autogenerate自動生成的遷移文件需要仔細審查,生成結果不總是符合預期- 對于不用 SQLAlchemy ORM、直接寫原生 SQL 的項目,引入 Alembic 反而顯得笨重
所以我借鑒了 Alembic 最核心的兩個思想——遷移文件版本化和執(zhí)行歷史持久化——自己搭了一套更輕的方案:純 Python + 原生 SQL,沒有額外依賴,文件結構一眼看懂,團隊新人不需要任何學習成本就能上手。
這篇文章就介紹這套方案的設計思路和具體用法。
它能做什么
一句話:把數(shù)據庫的每一次結構變更,變成有版本記錄、可追溯、不重復執(zhí)行的代碼提交。
具體來說:
- 每次改表結構,寫成遷移文件,提交到代碼倉庫,和業(yè)務代碼一起走 Code Review
- 執(zhí)行器自動記錄哪些遷移跑過了,下次不會重復執(zhí)行
- 新同事拉代碼,跑一條命令,數(shù)據庫自動同步到最新狀態(tài)
- 多環(huán)境(本地 / 測試 / 生產)狀態(tài)一致,不靠人肉對齊
目錄結構
migrations/
user.py # users 表遷移
orders.py # orders 表遷移
coupons.py # coupons 表遷移
migrate.py # 遷移執(zhí)行器(項目根目錄)
結構很平,沒有嵌套。每張表對應一個遷移文件,執(zhí)行器放在根目錄。
遷移文件長什么樣
每個遷移文件定義兩個東西:要執(zhí)行的 SQL 列表,和執(zhí)行后的校驗語句。
sql = [
{
'id': 1, # 遷移編號,同一文件內唯一,只增不改
'sql': """
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
`id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`order_no` VARCHAR(32) NOT NULL UNIQUE,
`user_id` INT NOT NULL,
`total_amount` DECIMAL(12,2) NOT NULL,
`order_status` TINYINT NOT NULL DEFAULT 0,
`create_time` DATETIME NOT NULL
);
""",
},
]
checks = [
'SELECT COUNT(*) FROM `orders`', # 驗證表存在且可查詢
]
# ── 執(zhí)行器兼容格式,請勿修改 ──
migrations = [
{**item, 'checks': checks}
for item in sql
]
幾個值得注意的設計:
id 只增不改。 每條遷移一旦上線,id 就是它的"身份證",執(zhí)行器靠它判斷是否執(zhí)行過。改了 id 等于讓執(zhí)行器認不出它,可能重復執(zhí)行。
新需求追加新條目,不修改舊條目。 要給 orders 表加字段,不是改 id: 1 的 SQL,而是在后面追加 id: 2:
sql = [
{ 'id': 1, 'sql': "..." }, # 已執(zhí)行,保持不動
{
'id': 2,
'sql': """
ALTER TABLE `orders`
ADD COLUMN `source` TINYINT DEFAULT 0 COMMENT '訂單來源';
""",
},
]
這個規(guī)則保證遷移歷史是線性追加的,任何時間點都能重現(xiàn)數(shù)據庫狀態(tài)。
checks 是最后一道保險。 遷移跑完之后,執(zhí)行器會跑 checks 里的 SQL 做驗證。寫一條簡單的 SELECT COUNT(*) 就夠,主要是確認表存在、沒有語法錯誤導致建表失敗。
怎么用
查看當前狀態(tài)——哪些遷移已執(zhí)行、哪些待執(zhí)行:
python3 migrate.py --status
執(zhí)行所有待執(zhí)行的遷移:
python3 migrate.py
執(zhí)行器會按文件、按 id 順序跑,跑過的自動跳過,新增的自動執(zhí)行。
執(zhí)行記錄怎么存
執(zhí)行器會在數(shù)據庫里自動創(chuàng)建一張 _migration_history 表,記錄每條遷移的執(zhí)行狀態(tài):
| 字段 | 說明 |
|---|---|
| module | 遷移文件名(不含 .py),如 orders |
| migration_id | 遷移條目的 id |
| description | 描述 |
| executed_at | 執(zhí)行時間 |
這張表就是"已執(zhí)行"的權威記錄。下次跑遷移,執(zhí)行器查這張表,module + migration_id 已存在的全部跳過,只執(zhí)行新的。
不需要手動維護,不需要記憶,狀態(tài)完全由工具管理。
這個項目用到的三張表
作為示例,這套遷移方案管理了三張核心業(yè)務表:
users(用戶表):存用戶基本信息和積分,帶 added_by / updated_by 審計字段,方便追蹤數(shù)據是誰改的。
orders(訂單主表):覆蓋訂單全生命周期——從待支付到已完成或已取消,order_status 用 TINYINT 枚舉狀態(tài),建了組合索引 idx_user_status_time 支持按用戶+狀態(tài)+時間的高頻查詢。
coupons(優(yōu)惠券表):支持滿減(fixed)和折扣(percent)兩種類型,外鍵關聯(lián) users.id,min_amount 字段控制使用門檻。
三張表的結構變更都通過遷移文件管理,任何環(huán)境執(zhí)行 python3 migrate.py 都能同步到一致狀態(tài)。
新增遷移的完整流程
- 在
migrations/下找到對應的.py文件(或新建一個) - 在
sql列表末尾追加新條目,id遞增 - 運行
python3 migrate.py執(zhí)行
# 先看一眼狀態(tài),確認預期 python3 migrate.py --status # 沒問題就執(zhí)行 python3 migrate.py
提交代碼時,把遷移文件和業(yè)務代碼一起提交。其他環(huán)境拉代碼后跑一遍遷移命令,數(shù)據庫自動對齊。
和原生 Alembic 的區(qū)別
這套方案借鑒了 Alembic 的核心理念,但實現(xiàn)方式更直接:
| 原生 Alembic | 這套方案 | |
|---|---|---|
| 依賴 | SQLAlchemy + Alembic | 純 Python,無額外依賴 |
| 遷移文件 | 自動生成,帶版本哈希 | 手寫 SQL,結構固定 |
| 歷史記錄 | alembic_version 表 | _migration_history 表 |
| 版本管理 | 鏈式版本圖 | 線性 id 追加 |
| 適用場景 | SQLAlchemy ORM 項目 | 任何用原生 SQL 的項目 |
| 上手成本 | 需要理解版本鏈概念 | 看完本文即可上手 |
如果你的項目已經深度使用 SQLAlchemy ORM,直接上 Alembic 是更合適的選擇。這套方案更適合不用 ORM、直接寫 SQL、想要簡單可控的遷移流程的場景。
小結
數(shù)據庫變更管理這件事,越早規(guī)范越省事。等到線上出了"某個環(huán)境少了個字段"這種問題,排查起來很浪費時間。
這套方案的核心邏輯只有三條:
- 變更寫成文件,提交到倉庫,和代碼一起走版本管理
- id 只增不改,保證歷史可追溯
- 執(zhí)行器自動記錄狀態(tài),不靠人記憶哪條跑過
結構簡單,但把最容易出錯的環(huán)節(jié)都堵住了。
到此這篇關于Python中實現(xiàn)數(shù)據庫遷移的輕量級方案詳解的文章就介紹到這了,更多相關Python數(shù)據庫遷移內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python中tensorflow的argmax()函數(shù)的使用小結
在TensorFlow中,argmax()函數(shù)是一個非常重要的操作,它用于返回給定張量(Tensor)沿指定軸的最大值的索引,下面就來介紹一下argmax()的使用,感興趣的可以了解一下2025-05-05
python日記(使用TCP實現(xiàn)的對話客戶端和服務器)
這篇文章主要為大家介紹了python使用TCP實現(xiàn)的對話客戶端和服務器實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03

