Alembic 数据库迁移:异步引擎配置 + upgrade/downgrade + 自动导入 Model
一句话:Alembic是SQLAlchemy的数据库迁移工具,可以管理数据库结构的变更。在FastAPI项目中,Alembic常用于管理数据库schema的版本控制。
1. Alembic 基础
1.1 什么是Alembic?
graph LR A[Alembic] --> B[数据库迁移工具] A --> C[版本控制] A --> D[自动生成迁移脚本] A --> E[支持升级/降级] style A fill:#e1f5fe
Alembic:SQLAlchemy的数据库迁移工具,用于管理数据库结构的变更。
1.2 安装和初始化
# 安装
pip install alembic
# 初始化
alembic init alembic
1.3 配置文件
# alembic.ini
[alembic]
script_location = alembic
sqlalchemy.url = postgresql://user:pass@localhost/db
# sqlalchemy.url = %(DATABASE_URL)s
2. 异步引擎配置
2.1 异步配置
# alembic/env.py
import asyncio
from logging.config import fileConfig
from sqlalchemy import pool
from sqlalchemy.engine import Connection
from sqlalchemy.ext.asyncio import async_engine_from_config
from alembic import context
# this is the Alembic Config object
config = context.config
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name)
# for 'autogenerate' support
from app.models import Base
target_metadata = Base.metadata
def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode."""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def do_run_migrations(connection: Connection) -> None:
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
async def run_async_migrations() -> None:
"""Run migrations in 'online' mode with async engine."""
connectable = async_engine_from_config(
config.get_section(config.config_ini_section, {}),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
await connectable.dispose()
def run_migrations_online() -> None:
"""Run migrations in 'online' mode."""
asyncio.run(run_async_migrations())
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
3. 生成迁移脚本
3.1 自动生成
# 自动生成迁移脚本
alembic revision --autogenerate -m "添加用户表"
# 生成空迁移脚本
alembic revision -m "自定义迁移"
3.2 迁移脚本示例
# alembic/versions/xxx_添加用户表.py
"""添加用户表
Revision ID: xxx
Revises:
Create Date: 2026-07-21 12:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'xxx'
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('users',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=50), nullable=False),
sa.Column('email', sa.String(length=100), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=True)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_users_email'), table_name='users')
op.drop_table('users')
# ### end Alembic commands ###
4. 执行迁移
4.1 升级数据库
# 升级到最新版本
alembic upgrade head
# 升级一个版本
alembic upgrade +1
# 升级到指定版本
alembic upgrade xxx
4.2 降级数据库
# 降级一个版本
alembic downgrade -1
# 降级到指定版本
alembic downgrade xxx
# 降级到初始版本
alembic downgrade base
4.3 查看版本历史
# 查看当前版本
alembic current
# 查看版本历史
alembic history
# 查看指定版本的迁移脚本
alembic history -v
5. 自动导入 Model
5.1 自动导入配置
# alembic/env.py
import os
import sys
from pathlib import Path
# 将项目根目录添加到Python路径
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
# 导入所有模型
from app.models.user import User
from app.models.post import Post
# 或者使用自动导入
from app.models import Base
5.2 模型定义示例
# app/models/user.py
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.orm import relationship
from datetime import datetime
from app.database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(50), nullable=False)
email = Column(String(100), unique=True, index=True, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
# 关系
posts = relationship("Post", back_populates="author")
6. 高级用法
6.1 数据迁移
# 迁移脚本中的数据迁移
def upgrade() -> None:
# 创建新表
op.create_table('new_users',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('full_name', sa.String(length=100), nullable=False),
sa.PrimaryKeyConstraint('id')
)
# 迁移数据
op.execute("""
INSERT INTO new_users (id, full_name)
SELECT id, name || ' ' || last_name
FROM users
""")
# 删除旧表
op.drop_table('users')
# 重命名新表
op.rename_table('new_users', 'users')
6.2 条件迁移
def upgrade() -> None:
# 根据数据库类型执行不同操作
dialect = op.get_context().dialect.name
if dialect == 'postgresql':
# PostgreSQL特定操作
op.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm")
elif dialect == 'mysql':
# MySQL特定操作
pass
6.3 迁移测试
# 测试迁移脚本
def test_migration():
# 升级到最新版本
op.execute("alembic upgrade head")
# 验证表结构
result = op.get_bind().execute("SELECT * FROM users")
assert result.fetchone() is not None
# 降级
op.execute("alembic downgrade -1")
7. 实际案例
7.1 FastAPI项目集成
# app/database.py
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql+asyncpg://user:pass@localhost/db"
engine = create_async_engine(DATABASE_URL)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
# sqlalchemy.url = postgresql+asyncpg://user:pass@localhost/db
8. 常见坑点
1. 迁移脚本冲突
# 解决:及时拉取最新迁移脚本,解决冲突
git pull origin main
alembic merge -m "合并冲突"
2. 数据丢失
# 解决:在迁移脚本中备份数据
def downgrade() -> None:
# 备份数据
op.execute("CREATE TABLE users_backup AS SELECT * FROM users")
# 执行降级
op.drop_table('users')
3. 异步引擎配置错误
# sqlalchemy.url = postgresql://user:pass@localhost/db
核心要点
# 初始化
alembic init alembic
# 生成迁移
alembic revision --autogenerate -m "描述"
# 执行迁移
alembic upgrade head # 升级到最新
alembic downgrade -1 # 降级一个版本
# 查看版本
alembic current # 当前版本
alembic history # 版本历史
速记卡(面试闪卡)
Q1:一句话讲清「Alembic 数据库迁移:异步引擎配置 + upgrade/downgrade + 自动导入 Model」到底是什么?
A:Alembic 是 SQLAlchemy 的数据库迁移工具,像给库结构写带版本号的变更日记,升级降级可追溯。
Q2:Alembic 是什么(migration) —— 怎么理解?
A:类比:把数据库结构想象成乐高说明书:每次改动都生成一页带编号的”修订页”(revision),队友照着翻到第几版就能复现同样的积木造型。Alembic 就是管这批修订页的版本控制系统。(Versioned schema)
Q3:异步引擎怎么配(async engine) —— 怎么理解?
A:类比:普通连接像打电话要等人接,异步引擎(async engine)像发微信——await 一下就去干别的,连接空档不浪费。env.py 里用 async_engine_from_config 配好 asyncpg 驱动,迁移时连接池不卡主线程。(Non-blocking IO)
Q4:自动生成迁移脚本(autogenerate) —— 怎么理解?
A:类比:你改了 Model 类,Alembic 像勤快秘书自动对比当前库和代码差异,敲一行 alembic revision --autogenerate 就起草好 upgrade/downgrade 两个方向变更稿,你只需校对签字。(Diff & draft)
Q5:自动导入 Model(import Base) —— 怎么理解?
A:类比:Model 散落各处,Alembic 翻译时得先认识它们。把项目根塞进 sys.path 再 import 所有 Model(或挂到 Base.metadata),就像给翻译官发全公司花名册,生成 SQL 才不会”查无此人”漏表。(Register metadata)
Q6:核心速记主线有哪些?
-
Alembic 是 SQLAlchemy 的迁移/版本控制工具(migration)
-
异步引擎用 async_engine_from_config + asyncpg,不堵主线程
-
revision —autogenerate 自动比对 Model 与库差异起草脚本
-
upgrade head 前进 / downgrade -1 回滚,current/history 看版本
-
自动导入 Model 靠 sys.path + import Base.metadata,避免漏表
口诀
A:Alembic 管版本,迁移 revision;
升级前进 head,回滚 downgrade;
异步配 asyncpg,autogenerate 起草;
Model 先导入,改表错不了。
相关链接
-
📋 目录:00-工程化与部署
-
📚 学习清单:技术学习路线图 > 工程化与部署