title: 多数据库迁移的艺术:Alembic在复杂环境中的精妙应用

date: 2025/05/11 00:35:52

updated: 2025/05/11 00:35:52

author: cmdragon

excerpt:

现代Web应用中,多数据库场景包括主从架构、多租户系统、混合数据库和分库分表。Alembic支持多数据库配置,通过创建多版本目录结构和修改alembic.ini文件实现。环境脚本(env.py)需改造以支持多数据库迁移。模型定义推荐使用pydantic结合SQLAlchemy ORM。迁移操作包括生成独立脚本、执行迁移和查看历史。常见报错如未初始化版本表、缺少数据库配置和模型类未绑定元数据,均有相应解决方案。

categories:

  • 后端开发
  • FastAPI

tags:

  • 多数据库迁移
  • Alembic配置
  • SQLAlchemy ORM
  • 数据库架构
  • 数据模型
  • 迁移脚本
  • 错误处理


扫描二维码

关注或者微信搜一搜:编程智域 前端至全栈交流与成长

探索数千个预构建的 AI 应用,开启你的下一个伟大创意https://tools.cmdragon.cn/

  1. 多数据库环境下的迁移需求分析

    现代Web应用中常见以下多数据库场景:
  • 主从数据库架构(读写分离)
  • 多租户系统(不同租户使用独立数据库)
  • 混合数据库类型(MySQL+PostgreSQL组合使用)
  • 分库分表架构(水平拆分业务模块)
  1. Alembic多数据库配置方法

    创建多版本目录结构:
project/
├── alembic/
│ ├── versions/
│ │ ├── db1/
│ │ └── db2/
│ └── env.py
├── alembic.ini
└── app/
└── models.py

修改alembic.ini配置:

[alembic]
script_location = alembic [db1]
sqlalchemy.url = postgresql://user:pass@localhost/db1 [db2]
sqlalchemy.url = mysql://user:pass@localhost/db2

环境脚本改造(env.py):

from alembic import context

def run_migrations(engine_name):
config = context.config
section = config.get_section(engine_name)
url = section["sqlalchemy.url"] engine = create_engine(url)
with engine.connect() as connection:
context.configure(
connection=connection,
target_metadata=get_metadata(engine_name),
version_table=f'alembic_version_{engine_name}'
)
with context.begin_transaction():
context.run_migrations(engine_name) if context.is_offline_mode():
run_migrations('db1')
run_migrations('db2')
else:
for engine_name in ['db1', 'db2']:
run_migrations(engine_name)
  1. 模型定义最佳实践

    使用pydantic结合SQLAlchemy ORM:
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel class UserBase(BaseModel):
email: str
is_active: bool = True class UserCreate(UserBase):
password: str class UserDB(UserBase):
id: int Db1Base = declarative_base()
Db2Base = declarative_base() class Db1User(Db1Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
email = Column(String)
password_hash = Column(String)
is_active = Column(Boolean) class Db2Log(Db2Base):
__tablename__ = "logs"
id = Column(Integer, primary_key=True)
action = Column(String)
user_id = Column(Integer)
  1. 多数据库迁移操作指南

    生成独立迁移脚本:
alembic -n db1 revision --autogenerate -m "add users table"
alembic -n db2 revision --autogenerate -m "add logs table"

执行迁移命令:

alembic -n db1 upgrade head
alembic -n db2 upgrade head

查看迁移历史:

alembic -n db1 history --verbose
alembic -n db2 history --verbose
  1. 课后Quiz

    Q1:当需要为第三个数据库添加迁移支持时,应该修改哪些配置文件?

    A) 只需修改alembic.ini

    B) 修改env.py和alembic.ini

    C) 修改models.py和env.py

    D) 需要创建新的版本目录并修改所有配置文件

正确答案:B

解析:需要修改alembic.ini添加新的数据库配置段落,并在env.py中扩展迁移执行逻辑。模型定义可能需要新增基类,但不需要修改现有文件。

Q2:如何为不同数据库设置独立的迁移版本表?

A) 在模型类中指定__version_table__属性

B) 在env.py的context.configure中设置version_table参数

C) 修改alembic.ini的version_table配置项

D) 使用不同的迁移目录结构

正确答案:B

解析:context.configure()中的version_table参数允许为每个数据库引擎指定独立的版本表名称。

  1. 常见报错解决方案

    错误1:sqlalchemy.exc.NoSuchTableError: alembic_version

    原因:目标数据库未初始化迁移版本表

    解决:
alembic -n db1 revision --autogenerate --version-path=alembic/versions/db1
alembic -n db1 stamp head

错误2:KeyError: 'No such section: 'db3'

原因:alembic.ini缺少对应数据库配置

解决:

[db3]
sqlalchemy.url = sqlite:///db3.sqlite

错误3:SAWarning: Class <class 'app.models.Db1User'> does not have a __table__

原因:模型类未正确绑定到元数据

解决:

Db1Base.metadata.create_all(engine)  # 在应用启动时执行

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:多数据库迁移的艺术:Alembic在复杂环境中的精妙应用 | cmdragon's Blog

往期文章归档:

多数据库迁移的艺术:Alembic在复杂环境中的精妙应用的更多相关文章

  1. Flask学习笔记:数据库迁移操作flask-script+alembic/flask-migrate

    数据库迁移是将代码中模型类(即表)的修改同步到数据库中, flask-sqlalchemy的模型类一旦使用create_all()映射到数据库中后,对这个模型类的修改(例如添加了一个新的字段)就不会再 ...

  2. 转 【TTS】AIX平台数据库迁移到Linux--基于RMAN(真实环境)

    [TTS]AIX平台数据库迁移到Linux--基于RMAN(真实环境) http://www.cnblogs.com/lhrbest/articles/5186933.html 各位技术爱好者,看完本 ...

  3. SQL Server中使用数据库快照的方式来完成测试环境中数据库的轻量级备份还原操作

    在开发或者测试环境的数据库中,经常会发现有开发或者测试人员误删除表或者数据的情况,对于开发或者测试库,一般都没有安排定时的备份任务去备份数据库,一方面是由于存储资源有限,不太可能给开发或者测试环境准备 ...

  4. Code First 数据库迁移

    当 Entity Framework Code First 的数据模型发生改变时,默认会引发一个System.InvalidOperationException 的异常.解决方法是使用DropCrea ...

  5. EntityFramework CodeFirst 数据库迁移

    参考: https://msdn.microsoft.com/en-us/data/jj591621 https://msdn.microsoft.com/en-us/library/dd394698 ...

  6. 使用 Code First 数据库迁移

    当 Entity Framework Code First 的数据模型发生改变时,默认会引发一个System.InvalidOperationException 的异常.解决方法是使用DropCrea ...

  7. 数据库上云实践:使用Ora2pg进行数据库迁移

    目录 概述 重要 前置条件 配置环境 Win环境配置 linux环境配置 定义ORACLE_HOME环境变量 Ora2Pg使用方法 配置文件ora2pg_table.conf 配置文件解释:Oracl ...

  8. Flask从入门到精通之使用Flask-Migrate实现数据库迁移

    在开发程序的过程中,你会发现有时需要修改数据库模型,而且修改之后还需要更新数据库.仅当数据库表不存在时,Flask-SQLAlchemy 才会根据模型进行创建.因此,更新表的唯一方式就是先删除旧表,不 ...

  9. Flask flask-migrate 数据库迁移

    简介 flask-migrate是flask的一个扩展模块,主要是扩展数据库表结构的. 官方文档:http://flask-migrate.readthedocs.io/en/latest/ 使用: ...

  10. EF Code First Migrations数据库迁移

    1.EF Code First创建数据库 新建控制台应用程序Portal,通过程序包管理器控制台添加EntityFramework. 在程序包管理器控制台中执行以下语句,安装EntityFramewo ...

随机推荐

  1. pagehelper分页查询的一个坑,明明下一页没有数据了却还是返回了数据

    pagehelper分页查询的一个坑,明明下一页没有数据了却还是返回了数据 解决:关闭这该死的合理化,如下配置: pagehelper:# helperDialect: mysql reasonabl ...

  2. BUUCTF-Web方向21-25wp

    [HCTF 2018]admin 打开环境,有三处提示,一个跳转链接,一个登录注册,一个提示不是admin 点击hctf,无法访问 注册个账号,依旧无法查看,看来需要admin账号 弱口令 爆破密码 ...

  3. Spark - [03] 资源调度模式

    题记部分 一.Local模式 1.1.概述 Local模式就是运行在一台计算机上的模式,通常就是用于在本机上练手和测试的. 可以通过以下几种方式设置Master (1)local:所欲计算都运行在一个 ...

  4. java.lang.IllegalStateException: File name has been re-used with different files. (flume报错)

    报错日志: java.lang.IllegalStateException: File name has been re-used with different files. Spooling ass ...

  5. CF2029C New Rating

    思路(二分 + 数据结构优化DP) 大致题意为:一个值 \(x\) 初始为 \(0\),然后有一个数组 \(a\),遍历一次数组. 如果 \(a_i > x\),则 \(x + 1\). 如果 ...

  6. JS中的0和php中的0

    请注意:包含 0 的字符串 "0" 是 true 一些编程语言(比如 PHP)视 "0" 为 false.但在 JavaScript 中,非空的字符串总是 tr ...

  7. 在php类中使用函数

    好久没更新了,今天复习歪麦编写php框架的文章,看到几个函数,在类中使用时,当参数需要调用类的方法时,都用数组的方式传参. 1.  spl_autoload_register(array($this, ...

  8. allure 报告环境搭建

    1.安装 pip install allure-pytest 2.下载allure 地址: https://repo.maven.apache.org/maven2/io/qameta/allure/ ...

  9. JMeter 自定义的respCode不是0就报异常

    在实际使用中,后台其实已经对异常的进行了处理,response body 返回来的,都是正常的请求响应: 这个时候,则需要通过 respCode 进行判断该请求是否是有效响应. 如响应报文如下: { ...

  10. golang interface 转 string、int、float64

    interface{} interface{} 接口.interface{} 类型很多人都会混淆.interface{} 类型是没有方法的接口.由于没有 implements 关键字,所以说所有的类型 ...