常用命令

  1. 初始化

    alembic init
    
  2. 查看版本

    alembic history
    
  3. 切换版本

    • 升级 upgrade

      alembic upgrade <commit-name>
      
    • 降级 downgrade

      alembic downgrade <commit-name>
      
  4. 查看现在的版本

    alembic current
    
  5. 生成 sql: --sql 参数

    alembic upgrade head --sql
    

    注意:这样不会在数据库中直接执行迁移操作

流程示例

创建 almebic commit(version) 方法

  1. 编写自己的新版本 models 代码
  2. 创建版本

    • alembic 使用模板代码自动创建一部分迁移代码,并且创建一个 commit

      alembic revision --autogenerate -m 'your comment messages'
      
    • 版本代码包含了 upgrade() 函数和 downgrade() 函数,分别用于升级和降级数据库版本
  3. 检查和修改自动生成的代码

    • 检查 alembic 自动创建的代码是否正确,如果有错误或者不足的地方,手动改正或者添加功能
  4. 生成 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
      
  5. 执行数据库升级

    alembic upgrade head
    alembic upgrade <prev_version>:<new_version>
    

    注意:

    • 升级操作危险,最好备份数据库,以免数据丢失

创建迁移版本的细节

  1. alembic 不会自动创建历史记录备份和恢复代码,需要自己完善

    • 通过在 alembic 迁移脚本中使用数据库连接转换数据格式或者直接备份到本地

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      
      conn = 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, 但是传入数据不是。。。 错误
      • jsonb 字段, sql 插入或更新数据需要传入成 string 类型

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        
        infos = 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},
            )
  2. 数据表的名称变化,需要自己手动处理

    1
    2
    3
    4
    
    from alembic import op
    
    def upgrade():
        op.rename_table("old_table_name", "new_table_name")
  3. 数据表的列名变化,需要自己手动处理

    1
    2
    3
    4
    5
    
    from 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 结构信息

  1. 确保新数据库没有相关的表格
  2. 执行命令,创建最新版本

    alembic upgrade head
    

alembic 和备份数据

  1. alembic 不是一个数据备份工具
  2. 如果要做备份,可以在 alembic 的 upgrade 和 downgrade 函数中设置备份代码(手动添加)

数据库中没有 alembic 的版本号相关数据,怎么办

原因:

  1. 数据库中没有 alembic_version 表,或者没有 alembic_version.version_num 列和值

修复方法:

  1. 检查自己数据库的实际版本
  2. 修改数据库版本号到这个实际版本

    1
    
    alembic stamp your_revision_num