数据库实战:FastAPI + SQLAlchemy 2.0 + Alembic 从零搭建,踩坑实录
数据库实战FastAPI SQLAlchemy 2.0 Alembic 从零搭建踩坑实录前言在现代 Web 开发中数据库操作是核心环节之一。FastAPI 作为高性能异步框架与 SQLAlchemy 2.0 的组合堪称黄金搭档而 Alembic 则能帮助我们优雅地管理数据库迁移。本文将带你从零搭建一套完整的数据库操作环境并分享我在这条路上踩过的坑。## 环境搭建与依赖配置### 核心依赖版本- Python 3.10± FastAPI 0.104± SQLAlchemy 2.0.23± Alembic 1.13.0± asyncpg (异步 PostgreSQL 驱动)### 踩坑点 1SQLAlchemy 2.0 的异步模式SQLAlchemy 2.0 引入全新的异步 API与旧版本不兼容。新手容易混淆create_engine和create_async_engine。python# database.py - 数据库配置核心文件from sqlalchemy.ext.asyncio import create_async_engine, AsyncSessionfrom sqlalchemy.orm import sessionmaker, DeclarativeBase# 注意必须使用 async 前缀的引擎DATABASE_URL postgresqlasyncpg://user:passwordlocalhost:5432/testdbengine create_async_engine(DATABASE_URL, echoTrue)# AsyncSession 是异步会话工厂async_session sessionmaker( engine, class_AsyncSession, expire_on_commitFalse # 避免事务提交后对象过期)class Base(DeclarativeBase): passasync def get_db() - AsyncSession: 依赖注入获取数据库会话 async with async_session() as session: try: yield session await session.commit() except Exception: await session.rollback() raise finally: await session.close()## 模型定义与数据操作### 踩坑点 2异步操作中的上下文管理忘记在异步函数中使用async with或await会导致连接泄漏。以下是一个完整的用户模型示例python# models.py - 定义数据库模型from sqlalchemy import Column, Integer, String, DateTime, funcfrom sqlalchemy.orm import relationshipfrom database import Baseclass User(Base): __tablename__ users id Column(Integer, primary_keyTrue, indexTrue) username Column(String(50), uniqueTrue, nullableFalse, indexTrue) email Column(String(120), uniqueTrue, nullableFalse) created_at Column(DateTime(timezoneTrue), server_defaultfunc.now()) # 关系定义可选 # posts relationship(Post, back_populatesauthor) def __repr__(self): return fUser(id{self.id}, username{self.username})# schemas.py - Pydantic 模型用于 API 请求验证from pydantic import BaseModel, EmailStrfrom typing import Optionalfrom datetime import datetimeclass UserCreate(BaseModel): username: str email: EmailStrclass UserResponse(BaseModel): id: int username: str email: str created_at: datetime class Config: from_attributes True # 支持 ORM 模式## FastAPI 路由实现### 踩坑点 3异步 CRUD 操作的正确写法很多新手会忘记在数据库操作前加await或者错误地使用同步查询。以下是一个完整的用户管理 APIpython# main.py - FastAPI 应用主文件from fastapi import FastAPI, Depends, HTTPException, statusfrom sqlalchemy.ext.asyncio import AsyncSessionfrom sqlalchemy import selectfrom typing import Listfrom database import get_dbfrom models import Userfrom schemas import UserCreate, UserResponseapp FastAPI(titleUser Management API)app.post(/users/, response_modelUserResponse, status_codestatus.HTTP_201_CREATED)async def create_user(user_data: UserCreate, db: AsyncSession Depends(get_db)): 创建新用户 关键点使用 await 执行异步查询 # 检查用户名是否已存在 result await db.execute( select(User).where(User.username user_data.username) ) existing_user result.scalar_one_or_none() if existing_user: raise HTTPException( status_codestatus.HTTP_400_BAD_REQUEST, detailUsername already exists ) # 创建新用户 new_user User( usernameuser_data.username, emailuser_data.email ) db.add(new_user) await db.flush() # 确保获取到 id await db.refresh(new_user) # 刷新对象状态 return new_userapp.get(/users/{user_id}, response_modelUserResponse)async def get_user(user_id: int, db: AsyncSession Depends(get_db)): 获取单个用户 result await db.execute(select(User).where(User.id user_id)) user result.scalar_one_or_none() if not user: raise HTTPException(status_code404, detailUser not found) return userapp.get(/users/, response_modelList[UserResponse])async def list_users(skip: int 0, limit: int 10, db: AsyncSession Depends(get_db)): 分页获取用户列表 result await db.execute( select(User).offset(skip).limit(limit) ) users result.scalars().all() return users## Alembic 数据库迁移配置### 踩坑点 4异步引擎与 Alembic 的兼容性Alembic 默认使用同步引擎需要手动配置异步支持。以下是一个完整的迁移配置python# alembic/env.py - 关键配置部分from logging.config import fileConfigfrom sqlalchemy import engine_from_configfrom sqlalchemy import poolfrom alembic import contextimport asynciofrom sqlalchemy.ext.asyncio import create_async_engine# 导入你的 Base 和模型from database import Basefrom models import User # 确保模型被导入config context.configfileConfig(config.config_file_name)target_metadata Base.metadatadef run_migrations_offline(): 离线迁移模式 url config.get_main_option(sqlalchemy.url) context.configure( urlurl, target_metadatatarget_metadata, literal_bindsTrue, dialect_opts{paramstyle: named}, ) with context.begin_transaction(): context.run_migrations()def do_run_migrations(connection): 执行迁移的核心函数 context.configure( connectionconnection, target_metadatatarget_metadata ) with context.begin_transaction(): context.run_migrations()async def run_async_migrations(): 异步迁移入口关键修复 connectable create_async_engine( config.get_main_option(sqlalchemy.url), poolclasspool.NullPool, ) async with connectable.connect() as connection: await connection.run_sync(do_run_migrations) await connectable.dispose()def run_migrations_online(): 在线迁移模式使用异步 asyncio.run(run_async_migrations())if context.is_offline_mode(): run_migrations_offline()else: run_migrations_online()### 迁移命令示例bash# 初始化 Alembicalembic init alembic# 生成迁移脚本alembic revision --autogenerate -m create_users_table# 执行迁移alembic upgrade head# 回滚alembic downgrade -1## 踩坑总结与最佳实践### 常见问题速查表| 问题现象 | 原因 | 解决方案 ||---------|------|----------||AsyncSession对象未关闭 | 忘记使用async with| 始终使用上下文管理器 || 事务提交后对象属性为 None |expire_on_commitTrue| 设置为 False 或手动 refresh || 异步查询返回空结果 | 忘记await| 检查所有数据库操作前加 await || Alembic 迁移报连接错误 | 使用了同步引擎 | 配置异步引擎适配器 || 外键约束错误 | 模型定义顺序问题 | 确保关联模型先定义 |### 性能优化建议1.连接池配置根据并发量调整pool_size和max_overflow2.懒加载 vs 立即加载使用selectinload避免 N1 查询3.批量操作使用bulk_insert_mappings提高插入性能4.索引优化为常用查询字段添加索引### 最终可运行示例将以上代码整合后运行以下命令即可体验完整功能bash# 1. 创建虚拟环境python -m venv venvsource venv/bin/activate# 2. 安装依赖pip install fastapi uvicorn sqlalchemy alembic asyncpg pydantic# 3. 启动服务uvicorn main:app --reload# 4. 访问 API 文档# http://localhost:8000/docs## 总结通过本文我们从零搭建了一套完整的 FastAPI SQLAlchemy 2.0 Alembic 技术栈涵盖了环境配置、模型定义、异步 CRUD 操作、数据库迁移等关键环节。踩坑记录揭示了异步编程中常见的陷阱包括上下文管理、事务状态、引擎类型选择等。记住异步不是魔法而是需要严谨对待的编程范式。在实际项目中建议结合单元测试和集成测试来验证数据库操作的正确性同时关注 SQLAlchemy 2.0 的官方文档更新因为异步 API 仍在持续优化中。掌握这套技术栈你将能高效构建健壮的后端系统。

相关新闻

短剧全AI译制流程靠谱吗?实测出错后的补救机制

短剧全AI译制流程靠谱吗?实测出错后的补救机制

全AI流程的"靠谱"不在于永不出错,而在于出错后有没有低成本的补救机制。本文实测常见出错场景,逐一列出对应补救路径,而非空谈"零失误"。一、全AI流程的可靠性基础:核心环节已达规模化生产标准判断一个全AI流…

2026/10/25 15:35:46 阅读更多 →
Hyper-V虚拟Openwrt软路由拨号后局域网内设备访问上级光猫的方法

Hyper-V虚拟Openwrt软路由拨号后局域网内设备访问上级光猫的方法

在笔者的另一篇文章《Hyper-V安装lede软路由历程及注意事项》中详细叙述了我在Hyper-V中安装lede(openwrt)软路由的经历。当时部署是通过dhcp方式从上级路由获取ip上网的,由于上级路由本身就可以访问光猫,所以软路由下的设备自然而…

2026/10/26 1:53:28 阅读更多 →
2026年国内展厅设计公司推荐:五大头部展厅设计公司深度评分与选型研判

2026年国内展厅设计公司推荐:五大头部展厅设计公司深度评分与选型研判

从案例积累、设计能力、数字技术、工程落地、综合服务五大维度分析,帮助企业选择适合的展厅设计合作伙伴随着企业品牌升级和数字化展示需求不断提升,展厅已经从传统意义上的“装修空间”发展成为集品牌传播、产品展示、企业文化输出、客户体验于一体的综…

2026/10/26 8:27:24 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/28 23:48:14 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/29 8:45:01 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/29 9:52:56 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/28 22:10:30 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/29 9:51:34 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/29 8:44:28 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 16:58:40 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/29 9:42:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 19:25:09 阅读更多 →