Skip to main content
今日目标:将 Python 代码与 MySQL 数据库”联姻”。但我们今天不走寻常路,将直接学习 异步 (Async) 数据库交互。这是 FastAPI 高性能的关键——如果你的 web 很快,但数据库查询卡住了线程,那整个服务还是慢的。今天不只是写代码,而是要彻底理解 “为什么需要异步数据库”“SQLAlchemy 如何工作” 以及 “如何设计数据库模型”

学习内容 (30 mins)

在开始写代码前,先搞懂这些核心概念,否则后面的代码你会看得云里雾里。
同步 vs 异步 (Sync vs Async)同步方式(传统)
  • 服务员(线程)给厨师下单 → 站在窗口傻等菜做好 → 端菜
  • 这期间他不能服务其他客人
  • 如果有很多客人,需要很多服务员(线程),资源消耗大
异步方式(现代)
  • 服务员给厨师下单 → 转头去服务下一桌 → 等菜好了再回来端
  • 一个服务员可以同时服务多桌客人
  • 资源利用率高,性能更好
在 Web 开发中的应用
  • 数据库 IO:查询数据库需要等待网络和磁盘 IO
  • 同步方式:线程被阻塞,等待数据库响应
  • 异步方式:使用 await,线程可以去处理其他请求,数据库响应后再继续
性能对比
  • 同步:1000 个并发请求需要 1000 个线程(资源消耗大)
  • 异步:1000 个并发请求可能只需要 10 个线程(资源消耗小)
什么时候用异步?
  • 适合:IO 密集型操作(数据库查询、网络请求、文件读写)
  • 不适合:CPU 密集型操作(计算、图像处理)
什么是 SQLAlchemy?SQLAlchemy 是 Python 最流行的 ORM(Object-Relational Mapping)框架,用于将 Python 对象映射到数据库表。为什么需要 ORM?
  • 避免手写 SQL:使用 Python 对象操作数据库,更安全
  • 类型安全:IDE 支持好,减少错误
  • 数据库无关:可以轻松切换数据库(MySQL、PostgreSQL 等)
  • 自动迁移:配合 Alembic 可以自动管理数据库结构变更
SQLAlchemy 核心组件
  • Engine(引擎)
    • 数据库的”驱动器”,负责真正的网络连接
    • 一个应用通常只有一个 Engine 实例
    • 创建方式:create_async_engine(DATABASE_URL)
  • Session(会话)
    • 你的”临时工作区”
    • 对对象的改动(add、commit)都发生在这里
    • 每个请求应该有一个独立的 Session
    • 使用完后必须关闭,否则会泄漏连接
  • Model(模型)
    • Python 类(Class)与数据库表(Table)的映射关系
    • 继承 Base,定义表结构和字段
    • 示例:class User(Base): __tablename__ = "users"
异步 SQLAlchemy 的关键
  • create_async_engine:创建异步引擎(不是 create_engine
  • AsyncSession:使用异步会话(不是 Session
  • await:所有数据库操作都要加 await
  • 驱动选择:MySQL 用 aiomysql,PostgreSQL 用 asyncpg

代码任务 (90 mins)

1

环境准备

确保虚拟环境已激活,并安装必要的包:
2

任务 A:配置数据库核心 (Engine & Model)

新建 database.py 文件,配置数据库连接和模型。
代码解释
  • create_async_engine:创建异步引擎(不是 create_engine
  • mysql+aiomysql://:指定使用异步 MySQL 驱动
  • AsyncSessionLocal:会话工厂,用于创建数据库会话
  • Base:所有模型的基类
  • Column:定义数据库列
验证步骤
  1. 检查文件语法是否正确
  2. 尝试导入:python -c "from database import engine, User; print('OK')"
3

任务 B:编写 CRUD 接口

修改 18_main.py,实现数据库的增删改查操作。
代码解释
  • get_db():依赖函数,自动管理数据库会话的生命周期
  • select(User):新版 SQLAlchemy 查询语法
  • await db.execute():执行查询(必须加 await)
  • db.add():添加对象到会话
  • await db.commit():提交事务(必须加 await)
  • await db.refresh():刷新对象,获取数据库生成的值
运行脚本
验证步骤
  1. 启动服务器后,检查控制台是否输出 “Database tables created”
  2. 访问 http://localhost:8000/docs 打开 Swagger UI
  3. 测试创建用户:
    • 点击 POST /users/
    • 输入 username: "test_user"email: "test@example.com"
    • 执行,应该返回 201 和用户信息
  4. 测试查询用户列表:
    • 点击 GET /users/
    • 执行,应该看到用户列表
  5. 在数据库中验证:
常见错误
  • ModuleNotFoundError: No module named 'aiomysql' - 未安装 aiomysql,执行 pip install aiomysql
  • Can't connect to MySQL server - 数据库服务未启动或连接配置错误
  • Table 'infra_db.users' doesn't exist - 表不存在,检查是否执行了建表操作
  • RuntimeError: This event loop is already running - 异步事件循环冲突,检查代码中是否有同步调用

拓展任务 (30 mins)

挑战 1:数据库迁移 (Alembic)

任务:研究如何使用 Alembic 进行数据库迁移。步骤
  1. 安装 Alembic:pip install alembic
  2. 初始化:alembic init alembic
  3. 生成迁移:alembic revision --autogenerate -m "create users table"
  4. 执行迁移:alembic upgrade head
提示:生产环境必须使用 Alembic,不要用 Base.metadata.create_all()

挑战 2:关联查询

任务:创建一个 Post 模型,与 User 建立一对多关系。提示

今日产出物

  • database.py - 数据库配置和模型定义
  • 18_main.py - 完整的 CRUD API 实现

参考代码

查看参考代码

在 GitHub 查看完整的示例代码

在线运行

使用在线编辑器测试代码

实际应用场景

异步数据库在 API 开发中的应用

  • 高并发场景:处理大量并发请求,提高性能
  • 资源优化:减少线程数量,降低资源消耗
  • 响应速度:异步 IO 不会阻塞其他请求
  • 可扩展性:支持更多并发连接

ORM 设计最佳实践

  • 模型分离:将模型定义放在独立的文件中
  • 会话管理:使用依赖注入自动管理会话生命周期
  • 事务控制:合理使用 commit 和 rollback
  • 查询优化:使用 select 而不是 query,使用索引
  • 迁移管理:使用 Alembic 管理数据库结构变更
与 Day 19 的关联:今天学习的数据库操作,明天会学习如何将数据库配置移到环境变量,并使用 Docker 部署应用。

上一天: 依赖注入

Day 17 | 依赖注入与中间件

下一天: 生产部署

Day 19 | 环境变量与 Docker 部署