Alembic
文章目录
常用命令
初始化
alembic init
查看版本
alembic history
切换版本
升级 upgrade
alembic upgrade <commit-name>
降级 downgrade
alembic downgrade <commit-name>
查看现在的版本
alembic current
生成 sql:
--sql参数alembic upgrade head --sql
注意:这样不会在数据库中直接执行迁移操作
流程示例
创建 almebic commit(version) 方法
- 编写自己的新版本 models 代码
创建版本
alembic 使用模板代码自动创建一部分迁移代码,并且创建一个 commit
alembic revision --autogenerate -m 'your comment messages'
- 版本代码包含了 upgrade() 函数和 downgrade() 函数,分别用于升级和降级数据库版本
检查和修改自动生成的代码
- 检查 alembic 自动创建的代码是否正确,如果有错误或者不足的地方,手动改正或者添加功能
生成 sql – 检查生成的 sql 是否正确 (可选)
alembic upgrade head --sql alembic upgrade <prev_version>:<new_version> --sql
例子:
alembic upgrade 5ba0213257a5:58226b887555 --sql
版本号可以通过下述命令查询
alembic history
5ba0213257a5 -> 58226b887555 (head), your_comment 49ecfa973b14 -> 5ba0213257a5, your comment b32c9dbfc53a -> 49ecfa973b14, your comment <base> -> b32c9dbfc53a, your comment
执行数据库升级
alembic upgrade head alembic upgrade <prev_version>:<new_version>
注意:
- 升级操作危险,最好备份数据库,以免数据丢失
创建迁移版本的细节
alembic 不会自动创建历史记录备份和恢复代码,需要自己完善
通过在 alembic 迁移脚本中使用数据库连接转换数据格式或者直接备份到本地
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20conn = op.get_bind() values = dict( task_id=task_id, upload_datetime=upload_datetime, save_dir=save_dir, file_infos=infos, status=status, message=message, cleaned=cleaned, task_name=task_name, ) print("\n\n", "--" * 20, values) conn.execute( sa.text( # "INSERT INTO task_info (task_id, upload_datetime, save_dir, file_infos, status, message, cleaned, task_name) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)" "INSERT INTO task_info (task_id, upload_datetime, save_dir, file_infos, status, message, cleaned, task_name) VALUES (:task_id, :upload_datetime, :save_dir, :file_infos, :status, :message, :cleaned, :task_name)" ), values, )注意:
新版 sqlalchemy 只允许使用 sql 中包含
:key_name, 传入数据使用 dict(key_name=your_value) 这种方式处理数据- 实际测试 sql 包含
%s, %s, 传入数据使用 tuple, alembic 执行升级会报错, 需要 tuple 或 dict, 但是传入数据不是。。。 错误
- 实际测试 sql 包含
jsonb 字段, sql 插入或更新数据需要传入成 string 类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22infos = json.dumps(infos) # 转换成 str 类型 res = conn.execute( sa.text( """ SELECT * FROM task_info WHERE file_infos = NULL AND task_id = :task_id """ ), {"task_id": task_id}, ) if res and res.first(): conn.execute( sa.text( """ UPDATE task_info SET file_infos = :file_infos """ ), {"file_infos": infos}, )
数据表的名称变化,需要自己手动处理
1 2 3 4from alembic import op def upgrade(): op.rename_table("old_table_name", "new_table_name")数据表的列名变化,需要自己手动处理
1 2 3 4 5from alembic import op def upgrade(): op.alter_column("task_info", "upload_datetime", new_column_name="create_dt") # 把 task_info.upload_datetime 列名,重命名为 task_info.create_dt
FAQ
新的数据库地址,重建表格和 alembic 结构信息
- 确保新数据库没有相关的表格
执行命令,创建最新版本
alembic upgrade head
alembic 和备份数据
- alembic 不是一个数据备份工具
- 如果要做备份,可以在 alembic 的 upgrade 和 downgrade 函数中设置备份代码(手动添加)
数据库中没有 alembic 的版本号相关数据,怎么办
原因:
- 数据库中没有
alembic_version表,或者没有alembic_version.version_num列和值
修复方法:
- 检查自己数据库的实际版本
修改数据库版本号到这个实际版本
1alembic stamp your_revision_num
文章作者
上次更新 2025-02-24 (77fafc9)