跳到主要内容

数据库迁移

问题

Python 项目中如何做数据库迁移管理?Alembic 和 Django Migration 有什么区别?

答案

Alembic(SQLAlchemy 配套)

Alembic 是 SQLAlchemy 官方的迁移工具:

# 初始化
alembic init migrations

# 自动生成迁移脚本(对比模型和数据库差异)
alembic revision --autogenerate -m "add users table"

# 执行迁移
alembic upgrade head

# 回滚
alembic downgrade -1

生成的迁移文件:

migrations/versions/001_add_users_table.py
def upgrade():
op.create_table(
"users",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("name", sa.String(50), nullable=False),
sa.Column("email", sa.String(120), unique=True),
)
op.create_index("ix_users_email", "users", ["email"])

def downgrade():
op.drop_index("ix_users_email")
op.drop_table("users")

Django Migrations

Django 内置迁移系统,与 ORM 深度集成:

# 生成迁移文件
python manage.py makemigrations

# 执行迁移
python manage.py migrate

# 查看待执行的迁移
python manage.py showmigrations

# 回滚到指定迁移
python manage.py migrate myapp 0003

对比

特性AlembicDjango Migrations
绑定框架SQLAlchemyDjango
自动检测--autogeneratemakemigrations
版本管理线性链 + 分支有向无环图(DAG)
数据迁移op.execute()RunPython
合并迁移alembic mergesquashmigrations

数据迁移(Data Migration)

结构迁移之外,还需要迁移数据:

# Alembic 数据迁移
def upgrade():
# 先加字段
op.add_column("users", sa.Column("full_name", sa.String(100)))
# 再迁移数据
op.execute("UPDATE users SET full_name = first_name || ' ' || last_name")
# 最后删旧字段
op.drop_column("users", "first_name")
op.drop_column("users", "last_name")

常见面试问题

Q1: 迁移冲突怎么处理?

答案

团队协作时,两人同时创建迁移会产生分支。解决方案:

  • Alembicalembic merge -m "merge heads" 创建合并迁移
  • Djangopython manage.py makemigrations --merge

Q2: 生产环境如何安全执行迁移?

答案

  1. 先在 staging 环境测试迁移脚本
  2. 备份数据库后再执行
  3. 大表加字段使用 ALTER TABLE ... ADD COLUMN ... DEFAULT NULL(避免锁表)
  4. 拆分迁移:结构变更和数据迁移分开执行
  5. 确保迁移脚本有 downgrade(可回滚)

Q3: 如何做零停机迁移?

答案

以"重命名字段"为例,需拆成多步:

  1. 添加新字段 → 部署代码(同时写新旧字段)
  2. 数据迁移(旧 → 新)
  3. 部署代码(只读新字段)
  4. 删除旧字段

相关链接