本文将会介绍如何使用Alembic工具来实现MySQL数据库迁移。
在我们的平时工作中,有时候需要对MySQL数据库表结构做些修改,那些有没有方便的工具来帮助我们更好更高效地进行这些操作呢?
Alembic
是一款轻量级的数据库迁移工具,主要用于管理和更新数据库结构。它与SQLAlchemy一起工作,为Python应用程序提供数据库版本管理功能。
主要特点:
SQLAlchemy集成:Alembic使用SQLAlchemy作为底层引擎,能够自动检测数据库结构变化并生成相应的迁移脚本。
自动迁移脚本生成:通过alembic revision
--autogenerate命令,可以自动根据ORM模型的变化生成迁移脚本34。
升级和降级支持:提供upgrade和downgrade命令,允许数据库结构升级到最新版本或降级到之前的版本。
离线迁移支持:可以生成SQL脚本以支持离线迁移。
下面将会介绍如何使用Alembic
工具来实现MySQL数据库迁移。
在这里,我们使用的数据库为MySQL,使用Docker方式启动,ORM框架选择sqlalchemy
.
创建新表
我们先创建两张新表school
和student
,项目结构如下:
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 from sqlalchemy import create_enginefrom sqlalchemy.orm import declarative_base DATABASE_URL = "mysql+pymysql://root:root@localhost:3306/orm_test" engine = create_engine(DATABASE_URL, echo=True ) Base = declarative_base()
再创建School类,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from datetime import datetime as dtfrom sqlalchemy import Columnfrom sqlalchemy.dialects.mysql import INTEGER, VARCHAR, DATETIMEfrom src.models.sqlalchemy_db import Baseclass 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 from datetime import datetime as dtfrom sqlalchemy import Columnfrom sqlalchemy.dialects.mysql import INTEGER, VARCHAR, DATETIMEfrom src.models.sqlalchemy_db import Baseclass 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 from src.models.sqlalchemy_db import Base, enginefrom src.models.sqlalchemy_school import Schoolfrom 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
初始化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 osimport 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"
执行迁移脚本
这时候,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 2 52 a541a5f 862 -> 10 da2b f28c58 (head), update school and student table <base> -> 52 a541a5f 862, add address in school table
查看现在版本
命令如下:
输出如下:
版本回退
命令如下:
总结
本文主要介绍了如何使用Alembic工具来实现MySQL数据库迁移。
本文演示的Python代码以及Alembic操作已开源至Github,网址为:https://github.com/percent4/ORM_test
.
欢迎关注我的公众号NLP奇幻之旅 ,原创技术文章第一时间推送。
欢迎关注我的知识星球“自然语言处理奇幻之旅 ”,笔者正在努力构建自己的技术社区。