FastAPI + SQLAlchemy 2.0 + Alembic 从零搭建,踩坑实录 📅 发布时间:2026/7/15 16:40:40 👁️ 浏览次数: 开篇你是不是也半夜被报警吵醒过“叮——” 线上服务报错了sqlalchemy.exc.StatementError。原因可能就是顺手改了个模型字段名却忘了生成迁移脚本导致生产环境表结构对不上。这种经历我相信不少朋友都有过。尤其是从 FastAPI SQLAlchemy 起步的时候异步怎么配模型怎么写Alembic 为什么总是识别不到变更一个坑接一个坑。今天咱们就来聊聊从零到一搭一套靠谱的数据库层顺便把我踩过的坑都给你标上警示牌。 先理一下咱们要干的事 第一部分为什么是这套组合聊聊选型逻辑 第二部分手把手搭环境从配数据库到写第一个模型 第三部分Alembic 接入与避坑自动生成脚本的那些坑 第四部分进阶思考连接池、异步、以及工程化建议️ 一、为什么是 FastAPI SQLAlchemy 2.0 Alembic咱们可以把 API 比作一家餐厅FastAPI 是那个手脚麻利的点餐员能快速把客人的需求HTTP请求传给后厨SQLAlchemy 就是后厨的食材管理员负责管理所有食材数据的进出和记录而Alembic 则是食材管理员的变更日志本每次新增食材或调整存储方式都得在本子上记一笔保证后厨和仓库一致。SQLAlchemy 2.0 之后语法更清爽了但同时也带来了一些变化——比如必须用 Mapped 和 mapped_column如果你还抱着 1.x 的写法跑起来就会报错。别问我怎么知道的我第一次升级项目时整个 models.py 一片飘红。️ 二、从零开始搭环境附代码可复制 安装依赖先装好这些包注意版本pip install fastapi uvicorn sqlalchemy alembic asyncpg # asyncpg 是 PostgreSQL 异步驱动这里多说一句如果你用 MySQL请装 aiomysql 或 asyncmy千万别装错否则异步引擎跑不起来。️ 项目结构myproject/ ├── app/ │ ├── __init__.py │ ├── database.py # 引擎、会话配置 │ ├── models.py # SQLAlchemy 模型 │ └── main.py # FastAPI 应用 ├── alembic.ini └── alembic/ # 迁移目录 配置数据库连接database.py这是最容易踩坑的地方。SQLAlchemy 2.0 推荐使用异步方式但很多人照抄旧代码配了个同步引擎然后和 FastAPI 的异步路由打架。from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession from sqlalchemy.orm import DeclarativeBase DATABASE_URL postgresqlasyncpg://user:passlocalhost/dbname # 创建异步引擎 engine create_async_engine(DATABASE_URL, echoTrue) # echoTrue 会打印SQL开发时很有用 # 创建异步会话工厂 AsyncSessionLocal async_sessionmaker(engine, expire_on_commitFalse) # 基类所有模型都要继承它 class Base(DeclarativeBase): pass注意看我用了create_async_engine和async_sessionmaker这才是异步的正确姿势。echoTrue 在开发时打开能让你看到背后执行的 SQL但线上记得关掉否则日志会爆炸。 定义模型models.pySQLAlchemy 2.0 的新写法用Mapped和mapped_column替代老旧的 Column。刚开始我很不习惯但用顺手后发现类型提示更香了。from sqlalchemy.orm import Mapped, mapped_column from app.database import Base class User(Base): __tablename__ users id: Mapped[int] mapped_column(primary_keyTrue) name: Mapped[str] mapped_column(nullableFalse) email: Mapped[str] mapped_column(uniqueTrue, indexTrue) age: Mapped[int | None] # 允许为空的字段用 Optional 或 | None注意如果字段允许为空类型注解必须用 | None否则 mapped_column 会默认 nullableFalse。我一开始就漏了这个导致插入数据时一直报错。⚡ 在 FastAPI 中使用异步会话接下来咱们在 main.py 里写一个依赖每次请求生成独立的会话from fastapi import FastAPI, Depends from sqlalchemy.ext.asyncio import AsyncSession from app.database import AsyncSessionLocal from app import models app FastAPI() async def get_db() - AsyncSession: async with AsyncSessionLocal() as session: yield session app.get(/users) async def get_users(db: AsyncSession Depends(get_db)): result await db.execute(select(models.User)) users result.scalars().all() return users这里用了async with自动管理会话生命周期用完即关不会泄露连接。这是官方推荐的做法比手动 close 靠谱多了。 三、Alembic 接入与自动迁移现在模型有了但数据库里还没表呢。这时候 Alembic 就该登场了。很多人觉得 Alembic 麻烦但其实只要配一次后面爽到飞起。⚙️ 初始化 Alembicalembic init alembic这会在项目根目录生成 alembic.ini 和 alembic/ 文件夹。然后打开 alembic.ini修改数据库连接字符串sqlalchemy.url postgresqlasyncpg://user:passlocalhost/dbname注意这里必须用异步驱动格式否则后面生成迁移时会报错。 修改 env.py 支持异步这是最关键的一步默认生成的 env.py 是给同步用的我们需要改成异步模式。打开 alembic/env.py找到 run_migrations_online 函数修改如下from sqlalchemy.ext.asyncio import async_engine_from_config from sqlalchemy import pool import asyncio # 在 run_migrations_online 内部 def do_run_migrations(connection): context.configure(connectionconnection, target_metadatatarget_metadata) with context.begin_transaction(): context.run_migrations() async def run_async_migrations(): connectable async_engine_from_config( config.get_section(config.config_ini_section), prefixsqlalchemy., poolclasspool.NullPool, ) async with connectable.connect() as connection: await connection.run_sync(do_run_migrations) asyncio.run(run_async_migrations())这段代码的作用是让 Alembic 用异步引擎连接数据库然后通过run_sync调用同步的迁移配置。如果不改这里你执行迁移时会得到 “asyncpg can‘t run in sync” 之类的错误。这个坑我替你们填了直接复制就行。还有一处要更改否则会报错 env.py does not provide a MetaData object or sequence of objects to the contextfrom app.models import User # target_metadata None target_metadata User.metadata 生成并执行迁移alembic revision --autogenerate -m init user table alembic upgrade head运行第一条命令后去 alembic/versions/ 下检查生成的脚本。千万别直接相信自动生成的脚本有时候它可能漏掉索引或者把 nullable 搞反。我每次都会手动 review 一遍比如看有没有创建唯一约束有没有遗漏外键。这是线上事故的高发区。确认无误后执行 upgrade表就建好了。以后每次修改模型重复这两步即可。 四、进阶思考与注意事项 同步与异步的抉择如果你是新项目强烈建议用异步。但如果你维护的老项目是同步的也别急着重构。同步配合fastapi 的 run_in_threadpool也能用只是性能上限低一些。不过根据我的线上经验大部分业务场景异步的收益并没有想象中大除非你是高并发 IO 密集型。 连接池调优默认的连接池参数可能不适合你的并发量。在 create_async_engine 中可以调整engine create_async_engine(DATABASE_URL, pool_size20, max_overflow10)pool_size是核心连接数max_overflow是峰值时最多可以创建的额外连接数。
T-S推理在智能控制系统中的实战解析与MATLAB实现 1. T-S推理在智能控制中的核心价值 我第一次接触T-S推理是在研究生阶段的智能控制课程上。当时教授用了一个特别形象的比喻:传统控制就像用固定菜谱做菜,而T-S推理则像米其林大厨,能根据食材状态动态调整烹饪方式。这个比喻让我瞬间理解了T-S… 2026/3/31 0:16:10
Mojo调用Python生态的7种方式,第4种连PyTorch官方文档都没写!——混合编程兼容性白皮书首发 第一章:Mojo与Python混合编程全景概览Mojo 是一种兼具 Python 语法亲和力与系统级性能的现代编程语言,专为 AI 基础设施和高性能计算场景设计。它原生兼容 Python 生态,允许开发者在同一个项目中无缝调用 Python 模块、复用 NumPy/Torch 接口… 2026/5/17 11:02:56
Java后端服务集成MogFace:构建高并发人脸检测API Java后端服务集成MogFace:构建高并发人脸检测API 最近在做一个智慧园区的项目,其中有个需求是要实时分析出入口的监控视频流,快速识别出人脸并做后续的考勤、签到处理。最开始我们尝试用Python写了个检测服务,单机跑起来效果还行… 2026/3/31 0:16:00
告别VBA!用ChatGPT新功能一键生成精美PPT(附实战案例) 1. 为什么现在可以彻底告别VBA了?记得三年前我做季度汇报时,为了自动生成PPT熬了两个通宵写VBA脚本。当时同事看我对着代码编辑器抓狂的样子,还开玩笑说"你这哪是在做汇报,分明是在搞软件开发"。现在回想起来࿰… 2026/7/15 16:38:32
GeoServer开源地理空间服务器:从开发到部署的完整实战指南 GeoServer开源地理空间服务器:从开发到部署的完整实战指南 【免费下载链接】geoserver Official GeoServer repository 项目地址: https://gitcode.com/gh_mirrors/ge/geoserver GeoServer作为业界领先的开源地理空间数据服务器,为Web地图服务提供… 2026/7/15 16:36:32
GriddyCode:终极自定义代码编辑器的完整实现指南 GriddyCode:终极自定义代码编辑器的完整实现指南 【免费下载链接】griddycode A code editor made with Godot. Code has never been more lit! 项目地址: https://gitcode.com/GitHub_Trending/gr/griddycode GriddyCode是一款基于Godot引擎构建的高度可定制… 2026/7/15 16:34:31
Windows Home Server 2011安装实测:兼容性、文件共享与备份功能验证 这类老版本服务器系统的安装测试,最值得关注的不是功能有多新,而是能不能在现在的硬件上顺利跑起来,以及还能不能满足基本的文件共享和备份需求。Windows Home Server 2011 作为微软最后一版专门为家庭环境设计的服务器系统,虽然官… 2026/7/15 16:34:31
单片机----汇编语言入门知识点 1. 汇编语言与单片机的关系 当你第一次接触单片机编程时,可能会被各种高级语言(如C、Python)所吸引。但真正要深入理解硬件的工作原理,汇编语言是绕不开的一道坎。我在刚学习单片机时,也曾对汇编感到头疼——那些看似晦… 2026/7/15 16:30:30
vLLM 与 SGLang 推理框架性能横评:吞吐、延迟与成本深度解析 一、 引言:大模型推理框架的演进与挑战 随着大语言模型(LLM)应用从探索走向规模化部署,推理框架的性能、效率和成本已成为技术选型的核心考量。vLLM 凭借其创新的 PagedAttention 技术,在吞吐量优化上树立了标杆&… 2026/7/15 16:28:30
行星减速机的工作原理是什么?从齿轮运动关系到减速比计算 一、行星齿轮机构的组成 标准行星齿轮机构主要包括: 太阳轮; 行星轮; 内齿圈; 行星架。 太阳轮位于机构中心。 多个行星轮围绕太阳轮均匀布置,行星轮内侧与太阳轮外啮合,外侧与内齿圈内啮合。 行星轮通过轴… 2026/7/15 0:03:00
阅读Java开源框架源码的心得分享! 前几日闲来无事有幸看到了一位博主分享自己阅读开源框架源码的心得,看了之后也引发了我的一些深度思考。我们为什么要看源码?我们该怎么样去看源码? 其中前者那位博主描述的我觉得很全了(如下图所示),就不做… 2026/7/15 0:03:00
【LINUX】驱动 【LINUX驱动】【字符设备】【中断】【Platform】【网课 设备树】【GPIO】【PINCTRL】【INPUT】【IIC】【SPI】【网络驱动】【屏幕驱动】【一 设备树】【二 内核模块编译】【三 基本驱动框架】【四 Platform总线设备驱动框架】【五 驱动子系统】【六 综合】 2026/7/15 0:07:01
Git reset 与 revert 深度对比:5个关键差异与 3 种典型应用场景 Git Reset 与 Revert 深度对比:5个关键差异与3种典型应用场景在团队协作开发中,代码版本管理如同行走钢丝——一步失误可能导致整个项目陷入混乱。作为Git进阶用户,你是否曾在深夜面对错误的提交束手无策?是否在强制推送后收到同事… 2026/7/13 8:31:55
GitHub 学生包申请避坑:5个常见失败原因与开发者工具调试方案 GitHub 学生包申请技术排障指南:5个高频失败场景与开发者工具实战方案第一次尝试申请GitHub学生包时,我盯着屏幕上那个不断转圈的加载动画整整15分钟,最终只等来了一行冰冷的错误提示。这可能是许多开发者共同的经历——明明按照教程操作&… 2026/7/14 18:25:04
冒烟测试用例设计规范:5%-10%覆盖率下的3类核心场景与执行标准 冒烟测试用例设计的黄金法则:5%-10%覆盖率下的精准筛选策略在快节奏的敏捷开发环境中,冒烟测试作为质量保障的第一道防线,其重要性不言而喻。当测试资源有限而时间紧迫时,如何从海量测试用例中精准筛选出那关键的5%-10%࿰… 2026/7/14 5:09:41