使用Alembic进行数据迁移
在 大型 FastAPI 项目 中,数据库迁移(Database Migration)功能通常使用 Alembic 进行管理,并且存放在 migrations/ 目录下。
1. 数据库迁移的目录结构
在 FastAPI 项目中,数据库迁移的目录结构如下:
my_fastapi_project/
│── app/                      # 应用主目录
│   ├── core/                 # 核心配置
│   │   ├── database.py       # 数据库连接
│   │   ├── config.py         # 配置管理
│   │   ├── __init__.py
│── migrations/               # Alembic 迁移管理
│   ├── versions/             # 存放迁移版本文件
│   ├── env.py                # Alembic 配置文件
│   ├── script.py.mako        # 迁移模板
│   ├── README                # 迁移说明
│   ├── alembic.ini           # Alembic 配置
│── .env                      # 环境变量
│── requirements.txt          # 依赖项
│── alembic.ini               # Alembic 配置
│── Dockerfile                # Docker 配置
│── docker-compose.yml        # Docker-Compose 配置
│── README.md                 # 项目说明
其中:
 • migrations/:存放数据库迁移的所有内容。
 • migrations/versions/:存放具体的迁移版本文件(XXXX_initial_migration.py)。
 • migrations/env.py:Alembic 运行时的数据库环境配置。
 • alembic.ini:Alembic 全局配置文件。
2. 配置 Alembic 进行数据库迁移
第一步:安装 Alembic
pip install alembic
第二步:初始化 Alembic
在项目根目录运行:
alembic init migrations
执行后,会在项目目录下生成 migrations/ 目录,结构如下:
migrations/
│── versions/                  # 迁移版本文件夹
│── env.py                     # Alembic 运行时配置
│── script.py.mako             # 迁移模板
│── README                     # 说明文件
│── alembic.ini                # Alembic 配置文件
3. 配置 env.py 连接数据库
打开 migrations/env.py,找到 config = context.config,修改如下:
from logging.config import fileConfig
from sqlalchemy import engine_from_config, create_engine
from sqlalchemy import pool
from alembic import context
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
    fileConfig(config.config_file_name)
# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
from app.models import *  # noqa: F401
# target_metadata = mymodel.Base.metadata
from app.models.base import Base  # noqa: F401
# target_metadata = None
target_metadata = Base.metadata
# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.
from app.core.config import settings  # noqa: F401
config.set_main_option("sqlalchemy.url", settings.MYSQL_DATABASE_URL)
def run_migrations_offline() -> None:
    """Run migrations in 'offline' mode.
    This configures the context with just a URL
    and not an Engine, though an Engine is acceptable
    here as well.  By skipping the Engine creation
    we don't even need a DBAPI to be available.
    Calls to context.execute() here emit the given string to the
    script output.
    """
    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 run_migrations_online() -> None:
    """Run migrations in 'online' mode.
    In this scenario we need to create an Engine
    and associate a connection with the context.
    """
    # connectable = engine_from_config(
    #     config.get_section(config.config_ini_section, {}),
    #     prefix="sqlalchemy.",
    #     poolclass=pool.NullPool,
    # )
    engine = create_engine(settings.MYSQL_DATABASE_URL)
    with engine.connect() as connection:
        context.configure(
            connection=connection, target_metadata=target_metadata
        )
        with context.begin_transaction():
            context.run_migrations()
if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()
⚠️ 注意:
 • 需要导入 Base.metadata,否则 Alembic 无法识别你的数据模型。
 • DATABASE_URL 从 app/core/config.py 读取,保证与应用使用的数据库一致。
4. 创建数据库迁移
当你新增或修改模型时,运行以下命令:
alembic revision --autogenerate -m "Initial migration"
这将在 migrations/versions/ 目录中生成类似于:
migrations/versions/
│── 20240101123045_initial_migration.py
示例迁移文件 (20240101123045_initial_migration.py)
from alembic import op
import sqlalchemy as sa
# 迁移 ID(自动生成)
revision = '20240101123045'
down_revision = None  # 如果是第一个迁移,设置为 None
branch_labels = None
depends_on = None
def upgrade():
    """数据库升级操作"""
    op.create_table(
        'users',
        sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True),
        sa.Column('username', sa.String(length=50), nullable=False, unique=True),
        sa.Column('email', sa.String(length=100), nullable=False, unique=True),
        sa.Column('hashed_password', sa.String(length=200), nullable=False),
    )
def downgrade():
    """数据库降级操作(回滚)"""
    op.drop_table('users')
该文件:
 • upgrade():定义数据库表的新增、修改操作。
 • downgrade():定义数据库表的回滚操作。
5. 应用数据库迁移
创建迁移文件后,执行以下命令将其应用到数据库:
alembic upgrade head
 • 成功后,数据库中会创建 users 表。
如果需要回滚数据库(撤销迁移),可以执行:
alembic downgrade -1
或者回滚到指定版本:
alembic downgrade <revision_id>
6. 如何在 Docker 里运行数据库迁移?
如果你使用 Docker 进行部署,在 docker-compose.yml 里,你可以使用 entrypoint.sh 自动执行数据库迁移:
#!/bin/sh
# 等待数据库启动
sleep 5
# 运行 Alembic 迁移
alembic upgrade head
# 启动 FastAPI 应用
exec uvicorn app.main:app --host 0.0.0.0 --port 8000
然后在 Dockerfile 里添加:
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
7. 总结
✅ 数据库迁移代码存放在 migrations/ 目录下
✅ env.py 负责连接数据库和 ORM 绑定
✅ 使用 alembic revision --autogenerate 生成迁移文件
✅ 使用 alembic upgrade head 执行数据库迁移
✅ 可以在 Docker 部署时自动执行迁移
这样,你的 FastAPI 项目就可以安全地进行数据库结构变更,保持版本一致性!🚀
 
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号