alembic是sqlalchemy官方数据库迁移工具,通过版本化迁移脚本管理schema变更;需配置alembic.ini的sqlalchemy.url或env.py中的target_metadata,支持自动生成、升级、回滚及跨环境同步。

Alembic 本身不直接操作数据库,它只生成和执行迁移脚本;真正改表结构的是你运行 alembic upgrade 时底层调用的 SQLAlchemy DDL 语句。
初始化 Alembic 环境前必须配好 SQLALCHEMY_DATABASE_URI
Alembic 不读取 Flask-SQLAlchemy 或 FastAPI 的配置对象,它只认 alembic.ini 里的 sqlalchemy.url,或 env.py 中硬编码/动态加载的 URL。
- 别在
alembic.ini里写sqlalchemy.url = ${DATABASE_URL}就以为能自动继承环境变量——它不解析 shell 变量,得手动替换或改用env.py加载 - PostgreSQL 用户注意:URL 必须带
postgresql+psycopg2://(不是postgres://),否则alembic revision --autogenerate会报ModuleNotFoundError: No module named 'psycopg2' - SQLite 路径要用绝对路径,比如
sqlite:///./app.db在某些工作目录下会找不到文件,建议写成sqlite:////full/path/to/app.db
alembic revision --autogenerate 为什么没检测到模型变更?
Autogenerate 依赖 env.py 中 context.configure() 的 target_metadata 指向正确的 MetaData 对象,且该对象必须已从你的模型中收集了所有表定义。
- 常见错误:在
env.py里写了from models import Base,但Base.metadata是空的——因为模型模块没被真正导入(Python 模块未执行) - 解决方法:在
env.py的run_migrations_online()函数里,显式导入模型模块,例如from app.models import User, Post(不是只导入Base) - 如果用 Flask,推荐在
env.py开头加from flask import current_app,再用current_app.extensions['sqlalchemy'].db.metadata替代手写的target_metadata - 运行前先试
python -c "from app.models import Base; print(Base.metadata.tables.keys())",确保输出非空
迁移脚本里写 op.alter_column() 为什么 PostgreSQL 报错“cannot alter type of a column used by a view”?
这是 PostgreSQL 的限制:只要字段被视图、物化视图、函数依赖,ALTER COLUMN TYPE 就会失败,Alembic 默认生成的 op.alter_column() 不处理这类依赖。
- 不能靠加
post_upgrade回调绕过——DDL 已在upgrade()中提交,出错就中断 - 正确做法:手工编辑迁移脚本,把
op.alter_column()拆成三步:op.add_column()新字段 →op.execute("UPDATE ...")迁移数据 →op.drop_column()旧字段 - MySQL 用户注意:
op.alter_column()对nullable改动是安全的,但改type(如VARCHAR(50)→VARCHAR(100))可能锁表,生产环境慎用 - SQLite 不支持
ALTER COLUMN,Alembic 会自动 fallback 到“重建表”,但不会保留外键约束,需手动在upgrade()里补op.create_foreign_key()
最常被跳过的一步:每次 alembic upgrade head 后,务必检查数据库里 alembic_version 表的 version_num 是否与最新脚本名一致——不一致说明某次 upgrade 半途失败却没回滚,后续 autogenerate 会漏掉变更。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











