Alembic 是一款轻量型的数据库迁移工具,它与 SQLAlchemy 一起共同为 Python 提供数据库管理与迁移支持,为关系型数据提供创建、管理、更改和调用的管理脚本,协助开发和运维人员在系统上线后对数据库进行在线管理。
安装
Alembic是同步工具,仅支持同步数据库驱动,比如MySQL 同步驱动pymysql。
Alembic是 SQLAlchemy 作者编写的数据库迁移工具,不用独立安装SQLAlchemy。
pip install alembic pymysql
创建迁移环境
使用 Alembic 之前需要先建立一个 Alembic 脚本环境。 在工程目录下执行下面脚本
alembic init alembic
执行完命令后,会在工程目录下生成alembic目录和alembic.ini配置文件
├── alembic
│ ├── README
│ ├── env.py
│ ├── script.py.mako
│ └── versions
├── alembic.ini
alembic/script.py.mako - 迁移脚本模板alembic/versions用于存放各个版本的迁移脚本。
配置设置
1、配置数据库连接
[alembic]
# 方法1:直接在配置文件中设置(不推荐提交敏感信息)
sqlalchemy.url = driver://user:password@host:port/database
config = context.config
# # 导入你的 SQLAlchemy同步数据库连接
from database import SYNC_DATABASE_URL
config.set_main_option('sqlalchemy.url', SYNC_DATABASE_URL)
2、设置模型基类
打开脚本env.py
# 导入你的 SQLAlchemy Base
from database import Base # 根据你的项目结构调整
# 设置 target_metadata
target_metadata = Base.metadata
3、生成初始迁移脚本
alembic revision -m "init table migration"
在versions看到迁移脚本
alembic upgrade head
# 输出
# ...
# INFO [alembic.runtime.migration] Running upgrade -> 3c2156449d57, init table migration
查看数据库我们会看到alembic_version数据表。
通过上面步骤完成后,表示我们配置成功,并完成了初始脚本迁移
常用命令
# 基于模型更改自动生成迁移脚本
alembic revision --autogenerate -m "描述信息"
# 创建空白迁移脚本
alembic revision -m "描述信息"
# 升级到最新版本
alembic upgrade head
# 升级到特定版本
alembic upgrade ae1027a6acf
# 降级一个版本
alembic downgrade -1
# 降级到特定版本
alembic downgrade base # 回退到初始状态
# 查看当前版本
alembic current
# 查看历史
alembic history
# 查看详细历史
alembic history --verbose
# 检查是否需要迁移
alembic check
实战操作
# models.py
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.sql import func
from database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(50), unique=True, index=True, nullable=False)
email = Column(String(100), unique=True, index=True, nullable=False)
hashed_password = Column(String(255), nullable=False)
full_name = Column(String(100))
is_active = Column(Integer, default=1)
created_at = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime, onupdate=func.now())
模型创建完成后,还有修改env.py文件
# from database Base 在导入基类后导入模型类
from models import User # 这行很重要,要不--autogenerate不起作用
alembic revision --autogenerate -m "create_user_table"
# 在verisions生成了迁移脚本
# Generating alembic\versions\a591b3f651be_create_user_table.py ... done
数据库数据表变更
alembic upgrade head
# INFO [alembic.runtime.migration] Running upgrade 3c2156449d57 -> a591b3f651be, create_user_table
修改模型User的密码字段password
password = Column(String(255), nullable=False) #变更hashed_password为password
full_name = Column(String(100)) # 删除字段
deleted_at = Column(DateTime, default=None) # 新增软删除字段
执行自动生成脚本
alembic revision --autogenerate -m "edit_user_table"
上面我本意是把hashed_password 修改成passoword,自动生成迁移脚本直接变更为删除后重新添加了
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('users', sa.Column('password', sa.String(length=255), nullable=False))
op.add_column('users', sa.Column('deleted_at', sa.DateTime(), nullable=True))
op.drop_column('users', 'hashed_password')
# ### end Alembic commands ###
def
downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('users', sa.Column('hashed_password', mysql.VARCHAR(collation='utf8mb4_bin', length=255), nullable=False))
op.drop_column('users', 'deleted_at')
op.drop_column('users', 'password')
# ### end Alembic commands ###
「如果有数据的时候一定要注意了」 ,这时候我们要通过alter_column手动修改字段名,字段属性等。
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column(
'users',
'hashed_password',
new_column_name='password',
existing_type=sa.String(255),
existing_nullable=False
)
op.add_column('users', sa.Column('deleted_at', sa.DateTime(), nullable=True))
op.drop_column('users', 'full_name')
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column(
'users',
'password',
new_column_name='hashed_password',
existing_type=sa.String(255),
existing_nullable=False
)
op.drop_column('users', 'deleted_at')
op.add_column('users', sa.Column('full_name', mysql.VARCHAR(collation='utf8mb4_bin', length=100), nullable=True))
# ### end Alembic commands ###
常用操作参考
# 创建表
op.create_table()
op.create_index()
op.create_unique_constraint()
op.create_foreign_key()
op.create_primary_key()
# 修改表
op.add_column()
op.drop_column()
op.alter_column()
op.rename_table()
# 数据操作
op.execute("UPDATE table SET column = value")
op.bulk_insert(table, rows)
优劣势分析
对于新项目,并且使用SQLAlchemy 作为数据库ORM工具的,多人协作开发的时候我们可以使用Alembic做为迁移工具,它提供类似 Git 的版本控制系统,支持自动生成迁移脚本、灵活的升级降级操作和事务安全性。对于使用 SQLAlchemy 的 Python 项目,特别是在快速迭代开发阶段,Alembic 能显著提升数据库 schema 管理效率。