4. Alembic 迁移工具入门
Alembic 是 SQLAlchemy 团队开发的轻量级数据库迁移工具,专为 Python 异步与同步环境设计。它通过版本化迁移脚本管理数据库 Schema 的增量变更,是 Development 环境中保证数据库结构与代码模型一致性的核心组件。
4.1 Alembic 的核心作用
| 维度 | 说明 |
|---|---|
| 版本控制 | 每次 Schema 变更生成一个独立迁移脚本,支持升级(upgrade)与回滚(downgrade) |
| 模型同步 | 自动检测 SQLAlchemy 模型与当前数据库的差异,生成迁移代码 |
| 多环境适配 | 通过配置切换开发、测试、生产环境的数据库连接 |
| 异步支持 | 原生支持 asyncio 驱动,适配 asyncpg、aiomysql 等异步引擎 |
| 团队协作 | 迁移脚本纳入 Git 管理,团队成员可追溯、可复现数据库变更历史 |
开发环境最佳实践: 每次修改 SQLAlchemy 模型后立即生成迁移脚本,避免累积大量变更导致冲突。建议将迁移脚本与代码提交绑定。
4.2 安装 Alembic
推荐在虚拟环境中通过 pip 安装,同时安装异步数据库驱动:
# 安装 Alembic 核心
pip install alembic
# 安装异步 PostgreSQL 驱动(开发环境常用)
pip install asyncpg
# 安装异步 MySQL 驱动
pip install aiomysql
# 验证安装
alembic --version
版本兼容性注意: Alembic 1.13+ 对 SQLAlchemy 2.0+ 有更好的异步支持。请确保项目依赖中 SQLAlchemy 版本 ≥ 2.0,否则异步迁移功能可能受限。
4.3 初始化配置:alembic init
在项目根目录执行初始化命令,生成标准目录结构与配置文件:
# 初始化 Alembic 项目
alembic init alembic
执行后生成的文件结构如下:
your_project/
├── alembic/ # 迁移脚本目录
│ ├── versions/ # 版本迁移脚本存放处
│ │ └── .gitkeep # 占位文件
│ ├── env.py # 核心环境配置(关键文件)
│ ├── script.py.mako # 迁移脚本模板
│ └── README # 说明文件
└── alembic.ini # 全局配置文件
| 文件/目录 | 作用 |
|---|---|
| alembic.ini | 数据库连接字符串、日志级别、脚本位置等全局参数 |
| alembic/env.py | Python 运行时配置,定义如何加载模型、创建引擎、运行迁移 |
| alembic/versions/ | 存放每次生成的迁移脚本,按时间戳命名 |
| script.py.mako | Mako 模板,控制新迁移脚本的生成格式 |
4.4 env.py 文件结构解析
env.py 是 Alembic 迁移运行时的入口,控制数据库连接、模型加载、迁移上下文等核心逻辑。以下为适配异步开发环境的典型结构:
# alembic/env.py
import asyncio
from logging.config import fileConfig
from alembic import context
from sqlalchemy import pool
from sqlalchemy.ext.asyncio import async_engine_from_config
# 导入 SQLAlchemy 模型基类(所有模型继承自该 Base)
from app.models import Base
# Alembic Config 对象,读取 alembic.ini
config = context.config
# 配置日志
if config.config_file_name is not None:
fileConfig(config.config_file_name)
# 设置元数据,用于自动生成迁移
target_metadata = Base.metadata
def run_migrations_offline() -> None:
"""离线模式:仅生成 SQL 脚本,不连接数据库"""
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):
"""执行迁移的核心函数"""
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
async def run_async_migrations() -> None:
"""异步模式:使用 async engine 执行迁移"""
configuration = config.get_section(config.config_ini_section)
# 创建异步引擎
connectable = async_engine_from_config(
configuration,
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:
"""在线模式入口:根据配置选择同步或异步执行"""
# 检测是否使用异步驱动
url = config.get_main_option("sqlalchemy.url")
if url.startswith("postgresql+asyncpg") or url.startswith("mysql+aiomysql"):
asyncio.run(run_async_migrations())
else:
# 同步模式(兼容传统场景)
from sqlalchemy import create_engine
engine = create_engine(url, poolclass=pool.NullPool)
with engine.connect() as connection:
do_run_migrations(connection)
# 根据 Alembic 运行模式选择执行路径
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
env.py 关键配置项:
- target_metadata:必须指向 SQLAlchemy 的 Base.metadata,否则 Alembic 无法检测模型变更。
- async_engine_from_config:异步引擎工厂,自动读取 alembic.ini 中的连接参数。
- run_async_migrations:异步迁移执行函数,使用
connection.run_sync桥接同步迁移逻辑。 - url 前缀检测:通过连接字符串前缀自动切换同步/异步模式,提升配置灵活性。
4.5 Alembic 迁移工作流
4.6 常用迁移命令速查
| 命令 | 作用 | 开发环境使用频率 |
|---|---|---|
alembic init alembic |
初始化迁移目录与配置文件 | 仅项目启动时 1 次 |
alembic revision --autogenerate -m "描述" |
自动检测模型变更并生成迁移脚本 | 每次模型修改后 |
alembic upgrade head |
升级到最新版本 | 每日多次 |
alembic downgrade -1 |
回滚上一个版本 | 调试时使用 |
alembic history |
查看迁移历史记录 | 团队协作时常用 |
alembic current |
查看当前数据库版本 | 排查版本不一致时 |
异步迁移注意事项: 在 Development 环境中使用异步驱动时,务必在
alembic.ini 中配置正确的异步连接字符串,例如 postgresql+asyncpg://user:pass@localhost/dbname。同步连接字符串会导致异步迁移失败。