Alembic 数据库迁移教程

Alembic 数据库迁移教程

1. 简介

Alembic 是一个数据库迁移工具,专门为 SQLAlchemy 设计。它可以帮助我们:

  • 跟踪数据库模式的变化
  • 管理数据库版本
  • 在不同环境中同步数据库结构
  • 回滚数据库变更

2. 安装

pip install alembic

3. 初始化

在项目根目录下执行:

alembic init alembic

这将创建以下文件和目录:

alembic/
  ├── env.py           # 主要配置文件
  ├── README          # 说明文件
  ├── script.py.mako  # 迁移脚本模板
  └── versions/       # 存放迁移脚本的目录
alembic.ini           # Alembic 配置文件

4. 配置

4.1 修改 alembic.ini

找到 sqlalchemy.url 配置项,修改为你的数据库连接 URL:

sqlalchemy.url = mysql://username:password@localhost/dbname

4.2 修改 env.py

env.py 中导入你的模型:

from models.base import Base
target_metadata = Base.metadata

5. 常用命令

5.1 创建迁移脚本

# 自动检测模型变化并生成迁移脚本
alembic revision --autogenerate -m "描述信息"

# 创建空的迁移脚本
alembic revision -m "描述信息"

5.2 执行迁移

# 更新到最新版本
alembic upgrade head

# 更新到指定版本
alembic upgrade <revision>

# 回滚到上一个版本
alembic downgrade -1

# 回滚到指定版本
alembic downgrade <revision>

# 回滚到初始状态
alembic downgrade base

5.3 查看信息

# 查看当前版本
alembic current

# 查看历史版本
alembic history

# 查看历史版本(详细信息)
alembic history -v

6. 迁移脚本示例

"""add user table

Revision ID: 1234567890ab
Revises: 
Create Date: 2024-01-23 10:00:00.000000

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers
revision = '1234567890ab'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # 创建表
    op.create_table(
        'users',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('username', sa.String(50), nullable=False),
        sa.Column('email', sa.String(100), nullable=False),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('username'),
        sa.UniqueConstraint('email')
    )
    
    # 添加列
    op.add_column('users', sa.Column('created_at', sa.DateTime))
    
    # 创建索引
    op.create_index('idx_username', 'users', ['username'])

def downgrade():
    # 删除索引
    op.drop_index('idx_username', 'users')
    
    # 删除列
    op.drop_column('users', 'created_at')
    
    # 删除表
    op.drop_table('users')

7. 最佳实践

7.1 迁移前的准备

  1. 确保所有模型变更已完成
  2. 备份数据库
  3. 在测试环境中先测试迁移脚本

7.2 编写迁移脚本的建议

  1. 每个迁移脚本只做一件事
  2. 为迁移脚本写清晰的描述
  3. 确保 upgrade()downgrade() 函数是对应的
  4. 测试 downgrade() 函数

7.3 处理数据迁移

def upgrade():
    # 1. 创建新表
    op.create_table(...)
    
    # 2. 获取连接
    connection = op.get_bind()
    
    # 3. 迁移数据
    connection.execute(
        """
        INSERT INTO new_table (id, name)
        SELECT id, name FROM old_table
        """
    )
    
    # 4. 删除旧表
    op.drop_table('old_table')

8. 常见问题

8.1 自动生成没有检测到变更

可能的原因:

  • 模型没有正确导入
  • 元数据对象配置错误
  • 表已经存在于数据库中

解决方法:

  1. 检查 env.py 中的导入
  2. 确认 target_metadata 设置正确
  3. 手动编写迁移脚本

8.2 迁移执行失败

常见原因:

  • 数据库连接问题
  • SQL 语法错误
  • 数据不兼容

处理方法:

  1. 检查错误信息
  2. 回滚到上一个版本
  3. 修复问题后重新迁移

9. 与 FastAPI 集成

在 FastAPI 项目中使用 Alembic:

# config.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "mysql://user:password@localhost/dbname"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(bind=engine)

# env.py
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context
from config import SQLALCHEMY_DATABASE_URL
from models.base import Base

config = context.config
config.set_main_option("sqlalchemy.url", SQLALCHEMY_DATABASE_URL)
target_metadata = Base.metadata

def run_migrations_online():
    connectable = engine_from_config(
        config.get_section(config.config_ini_section),
        prefix="sqlalchemy.",
        poolclass=pool.NullPool,
    )
    with connectable.connect() as connection:
        context.configure(
            connection=connection,
            target_metadata=target_metadata
        )
        with context.begin_transaction():
            context.run_migrations()

10. 参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老大白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值