MySQL数据库迁移利器Alembic

本文将会介绍如何使用Alembic工具来实现MySQL数据库迁移。

在我们的平时工作中,有时候需要对MySQL数据库表结构做些修改,那些有没有方便的工具来帮助我们更好更高效地进行这些操作呢?

Alembic是一款轻量级的数据库迁移工具,主要用于管理和更新数据库结构。它与SQLAlchemy一起工作,为Python应用程序提供数据库版本管理功能。

主要特点:

  • SQLAlchemy集成:Alembic使用SQLAlchemy作为底层引擎,能够自动检测数据库结构变化并生成相应的迁移脚本。

  • 自动迁移脚本生成:通过alembic revision --autogenerate命令,可以自动根据ORM模型的变化生成迁移脚本34。

  • 升级和降级支持:提供upgrade和downgrade命令,允许数据库结构升级到最新版本或降级到之前的版本。

  • 离线迁移支持:可以生成SQL脚本以支持离线迁移。

下面将会介绍如何使用Alembic工具来实现MySQL数据库迁移。

在这里,我们使用的数据库为MySQL,使用Docker方式启动,ORM框架选择sqlalchemy.

创建新表

我们先创建两张新表schoolstudent,项目结构如下:

1
2
3
4
5
6
7
$ tree models
models
├── __init__.py
├── sqlalchemy_db.py
├── sqlalchemy_init_db.py
├── sqlalchemy_school.py
└── sqlalchemy_student.py

首先创建基类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
# -*- coding: utf-8 -*-
# @file: sqlalchemy_db.py
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base

# 创建MySQL数据库引擎
DATABASE_URL = "mysql+pymysql://root:root@localhost:3306/orm_test"
engine = create_engine(DATABASE_URL, echo=True)

# 创建共享的 Base 类
Base = declarative_base()

再创建School类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding: utf-8 -*-
# @file: sqlalchemy_school.py
from datetime import datetime as dt
from sqlalchemy import Column
from sqlalchemy.dialects.mysql import INTEGER, VARCHAR, DATETIME

from src.models.sqlalchemy_db import Base


class School(Base):

__tablename__ = 'school'

id = Column(INTEGER, primary_key=True, autoincrement=True)
insert_time = Column(DATETIME, default=dt.now())
update_time = Column(DATETIME, default=dt.now(), onupdate=dt.now())
is_deleted = Column(INTEGER, default=0)
name = Column(VARCHAR(256), nullable=False)
address = Column(VARCHAR(256), nullable=False)
phone = Column(VARCHAR(256), nullable=False)

然后创建School类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- coding: utf-8 -*-
# @file: sqlalchemy_student.py
from datetime import datetime as dt
from sqlalchemy import Column
from sqlalchemy.dialects.mysql import INTEGER, VARCHAR, DATETIME

from src.models.sqlalchemy_db import Base


class Student(Base):
__tablename__ = 'student'

id = Column(INTEGER, primary_key=True, autoincrement=True)
insert_time = Column(DATETIME, default=dt.now())
update_time = Column(DATETIME, default=dt.now(), onupdate=dt.now())
is_deleted = Column(INTEGER, default=0)
name = Column(VARCHAR(256), nullable=False)
age = Column(VARCHAR(256), nullable=False)
gender = Column(VARCHAR(10), nullable=False)

最后是新建表格,代码如下:

1
2
3
4
5
6
7
8
9
# -*- coding: utf-8 -*-
# @file: sqlalchemy_init_db.py
from src.models.sqlalchemy_db import Base, engine
from src.models.sqlalchemy_school import School
from src.models.sqlalchemy_student import Student

# 创建表
Base.metadata.create_all(bind=engine)
print('Create table successfully!')

运行代码后,就会在MySQL中创建上述两张表格,表结构描述如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> desc school;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| insert_time | datetime | YES | | NULL | |
| update_time | datetime | YES | | NULL | |
| is_deleted | int | YES | | NULL | |
| name | varchar(256) | NO | | NULL | |
+-------------+--------------+------+-----+---------+----------------+

mysql> desc student;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| insert_time | datetime | YES | | NULL | |
| update_time | datetime | YES | | NULL | |
| is_deleted | int | YES | | NULL | |
| name | varchar(256) | NO | | NULL | |
| age | varchar(256) | NO | | NULL | |
+-------------+--------------+------+-----+---------+----------------+

数据库迁移

安装Alembic

1
pip install alembic

初始化Alembic

切换至models上级目录src,运行命令:

1
2
cd src
alembic init alembic

此时,在models同级目录会出现alembic.ini文件以及migration文件夹。

修改alembic.ini配置文件

1
2
# sqlalchemy.url = driver://user:pass@localhost/dbname
sqlalchemy.url = mysql+pymysql://root:root@localhost/test

修改migration/env.py配置文件

修改migration文件夹下的env.py配置文件。

1
2
3
4
5
6
import os
import sys
# 返回当前路径的上级路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from models.sqlalchemy_init_db import Base
target_metadata = Base.metadata

修改响应的MySQL表结构,创建迁移脚本

我们在School类中添加address字段,然后使用alembic创建迁移脚本。

1
$ alembic revision --autogenerate -m "add address in school table"

执行迁移脚本

1
alembic upgrade head

这时候,school表中就会新增address字段。

1
2
3
4
5
6
7
8
9
10
11
mysql> desc school;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| insert_time | datetime | YES | | NULL | |
| update_time | datetime | YES | | NULL | |
| is_deleted | int | YES | | NULL | |
| name | varchar(256) | NO | | NULL | |
| address | varchar(256) | NO | | NULL | |
+-------------+--------------+------+-----+---------+----------------+

再次更新表结构

按照上述的autogenerate和upgrade步骤,我们在此对结构进行修改,在school表中新增phone字段,在student表中新增gender字段。

更多操作

我们观察下此时的数据库,里面会多出一张名为``的表格,里面记录了使用alembic生产的版本号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> show tables;
+--------------------+
| Tables_in_orm_test |
+--------------------+
| alembic_version |
| school |
| student |
+--------------------+

mysql> desc alembic_version;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| version_num | varchar(32) | NO | PRI | NULL | |
+-------------+-------------+------+-----+---------+-------+

查看alembic历史

命令如下:

1
alembic history

输出如下:

1
2
52a541a5f862 -> 10da2bf28c58 (head), update school and student table
<base> -> 52a541a5f862, add address in school table

查看现在版本

命令如下:

1
alembic current

输出如下:

1
2
...(内容省略)
10da2bf28c58 (head)

版本回退

命令如下:

1
alembic downgrade -1

总结

本文主要介绍了如何使用Alembic工具来实现MySQL数据库迁移。

本文演示的Python代码以及Alembic操作已开源至Github,网址为:https://github.com/percent4/ORM_test .

欢迎关注我的公众号NLP奇幻之旅,原创技术文章第一时间推送。

欢迎关注我的知识星球“自然语言处理奇幻之旅”,笔者正在努力构建自己的技术社区。


MySQL数据库迁移利器Alembic
https://percent4.github.io/MySQL数据库迁移利器Alembic/
作者
Jclian91
发布于
2025年4月27日
许可协议