技术分享FastAPIAlembic数据库迁移
数据库迁移翻车现场:Alembic救了我
2025/8/319 min75 次观看
第一次用Alembic踩坑实录,生产环境数据库迁移要注意啥
01 事故现场
上周我信心满满地给线上数据库加了字段:
# app/models/post.py
class Post(Base):
# ... 其他字段
view_count: Mapped[int] = mapped_column(default=0) # 新增
然后直接重启服务...
boom! 服务启动失败,数据库报错:列不存在。
后来才知道,create_all()只能创建新表,不能修改已有表结构。我需要Alembic!
02 Alembic初体验
安装:
pip install alembic
alembic init alembic
配置alembic.ini:
sqlalchemy.url = postgresql+asyncpg://postgres:postgres@localhost:5432/blog_db
配置alembic/env.py,添加模型引用:
from app.models.base import Base
from app.models.user import User
from app.models.post import Post
from app.models.comment import Comment
from app.models.category import Category
target_metadata = Base.metadata
03 生成第一个迁移
alembic revision --autogenerate -m "create all tables"
生成的迁移文件:
# alembic/versions/xxxx_create_all_tables.py
"""create all tables
Revision ID: xxx
Revises:
Create Date: 2026-05-31 10:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
# revision, down_revision 需要手动填写
revision = 'xxx'
down_revision = None
def upgrade():
op.create_table('users', ...)
op.create_table('posts', ...)
def downgrade():
op.drop_table('posts')
op.drop_table('users')
执行迁移:
alembic upgrade head
04 添加新字段
后来需要给Post加view_count:
# app/models/post.py
view_count: Mapped[int] = mapped_column(default=0)
生成迁移:
alembic revision --autogenerate -m "add view_count to post"
# alembic/versions/xxxx_add_view_count.py
def upgrade():
op.add_column('posts', sa.Column('view_count', sa.Integer(), nullable=True))
def downgrade():
op.drop_column('posts', 'view_count')
执行:
alembic upgrade head
完美!
05 我踩过的坑
坑1:autogenerate检测不到所有变更
# 这种改名autogenerate检测不到
name = Column('name', String(50)) # 改为
name = Column('username', String(50))
# 需要手写迁移
def upgrade():
op.alter_column('users', 'name', new_column_name='username')
坑2:生产环境先演练
# 先检查有哪些迁移
alembic history
# 在测试库演练一遍
alembic upgrade head --database=postgresql://test@localhost/test_db
坑3:迁移顺序要填对
# 生成的迁移文件默认down_revision是None
revision = 'abc123'
down_revision = None # 错了!应该填上一个版本的revision
# 要改成上一个版本
down_revision = 'xyz789'
06 总结
- 不用create_all(),用Alembic管理数据库版本
- 生成迁移后要检查, autogenerate不是万能的
- 生产环境先测试,备份!备份!备份!
- down_revision要填对,保证迁移可回滚
# 常用命令
alembic revision --autogenerate -m "描述" # 生成迁移
alembic upgrade head # 升级到最新
alembic downgrade -1 # 回滚一个版本
alembic history # 查看迁移历史
alembic current # 查看当前版本