Skip to content

MySQL 8.0 与数据持久化基础 ​

本手册的数据库学习路线 ​

数据库部分统一使用 MySQL 8.0 + Tortoise ORM。这一章先认识 MySQL 和基本 SQL;第 26~41 章详细学习 ORM。建议顺序:第 15 章 → 第 26、27 章 → 第 28~32 章 → 三种关系 → 事务 → 完整接口与测试。

MySQL 是独立运行的数据库服务器,Tortoise 是 Python 程序与数据库之间的 ORM 工具。安装一个 Python 包不会自动安装或启动 MySQL 服务。

text
客户端请求
    ↓
FastAPI 路由函数
    ↓ await
Tortoise ORM:把操作组织成 SQL
    ↓
asyncmy:负责异步数据库通信
    ↓
MySQL 8.0:真正保存、查询和约束数据

数据库的基本概念 ​

概念通俗解释任务项目中的例子
数据库一组相关表的容器fastapi_learning
表按统一结构保存记录todos
行一条记录一条待办任务
列一种属性title、done
主键唯一定位一行id
外键指向另一张表的记录owner_id 指向用户
唯一约束不允许重复值或重复组合用户名不能重复
索引帮助某些查询快速定位数据用户编号和完成状态的联合索引
事务多个修改作为一个整体完成转账中的扣款和入账
连接池准备并复用有限数量的连接省去每次从零建立连接

准备 MySQL 8.0 ​

已经安装并运行 MySQL 8.0 可以跳过安装。尚未安装时,按 MySQL 8.0 官方 Windows 安装说明 安装对应版本的 Server,记下管理员密码与端口。

命令行客户端和 Workbench 是操作工具;真正保存数据的是 Server。安装 Workbench 并不代表 Server 已经安装。

在 PowerShell 中登录本机数据库:

powershell
mysql -h 127.0.0.1 -P 3306 -u root -p

-P 是端口,-p 是交互输入密码。若 mysql 命令找不到,使用实际安装目录中的 mysql.exe,或配置其 bin 路径。

进入 MySQL 后执行以下 SQL,不要直接粘贴到 PowerShell:

sql
SELECT VERSION();
SELECT @@default_storage_engine, @@character_set_server, @@collation_server;

版本结果应为 8.0.x。本手册要求的是 8.0,不能仅因某个镜像叫 mysql:8 就认定它是 8.0;实际版本需要查询确认。

创建学习数据库与专用账号 ​

在管理员连接中执行;先将示例密码替换成自己的密码:

sql
CREATE DATABASE fastapi_learning
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_0900_ai_ci;

CREATE USER 'fastapi_user'@'127.0.0.1'
  IDENTIFIED BY 'ReplaceWithYourOwnStrongPassword';

GRANT SELECT, INSERT, UPDATE, DELETE,
      CREATE, ALTER, DROP, INDEX, REFERENCES
ON fastapi_learning.* TO 'fastapi_user'@'127.0.0.1';

如果库或账号已经存在,不要重复创建;确认原来的配置。账号由“用户名 + 允许来源主机”共同识别。容器、远程机器和本机可能被 MySQL 识别为不同来源,需要按实际连接来源授权。MySQL 建库说明、MySQL 账号说明

这里给学习账号提供了建表权限,方便初次实验。正式项目可以把运行账号与执行迁移的账号分开,运行账号只获得所需数据操作权限。

再用应用账号连接,验证自己确实能访问学习库:

powershell
mysql -h 127.0.0.1 -P 3306 -u fastapi_user -p fastapi_learning

字符集与排序规则 ​

utf8mb4 可以保存中文和完整 Unicode 字符;utf8mb4_0900_ai_ci 是本示例选择的排序规则,其中 ci 表示比较通常不区分大小写,ai 表示通常不区分重音。MySQL 8.0 字符集说明

因此,唯一用户名 alice 与 Alice 在这种规则下可能冲突。字符串匹配是否区分大小写,也不能只凭 Python 字符串的行为推断。需要严格区分时,应按业务选择适当的列级排序规则并通过迁移应用。

先亲手完成一次 SQL 增删改查 ​

在学习库中新建一张独立演示表,它不与后面的 ORM 表同名:

sql
CREATE TABLE demo_notes (
  id INT PRIMARY KEY AUTO_INCREMENT,
  title VARCHAR(100) NOT NULL,
  done BOOLEAN NOT NULL DEFAULT FALSE
) ENGINE=InnoDB;

INSERT INTO demo_notes (title) VALUES ('学习 MySQL 8.0');
SET @demo_id = LAST_INSERT_ID();

SELECT id, title, done FROM demo_notes WHERE id = @demo_id;

UPDATE demo_notes SET done = TRUE WHERE id = @demo_id;
SELECT id, title, done FROM demo_notes WHERE id = @demo_id;

DELETE FROM demo_notes WHERE id = @demo_id;
SELECT id, title, done FROM demo_notes WHERE id = @demo_id;

@demo_id 是当前连接里的变量;LAST_INSERT_ID() 读取刚生成的自增编号。最后一次查询返回空结果,因为这一行已删除。

SQL在做什么后面对应的 ORM 思路
INSERT新增记录await Model.create(...)
SELECT查询记录await Model.filter(...)
UPDATE修改记录await Model.filter(...).update(...)
DELETE删除记录await Model.filter(...).delete()

ORM 让你少写重复 SQL,但数据库的主键、外键、索引与事务仍然需要理解。

持久化与事务要分清 ​

持久化回答“程序重启后数据是否还在”;事务回答“相关修改是否一起完成”。Tortoise 常规写操作通常按连接的自动提交行为完成;多步骤操作用 in_transaction() 明确组织,第 37 章会演示。

本示例使用 InnoDB,它支持事务和外键。创建表时可以通过 SHOW CREATE TABLE 表名 核对存储引擎和约束。MySQL InnoDB 表说明

学习时经常遇到的连接问题 ​

问题优先检查
连接拒绝或超时服务是否启动、主机和端口是否正确
Access denied用户、密码、允许来源主机是否匹配
Unknown database是否先创建了配置中的数据库
中文或 emoji 出错库、表、列、客户端连接的字符集
Python 程序重启后“查不到数据”是否连到了同一个库,是否有事务回滚
能连接但无法建表账号是否有建表及相关权限

本章练习 ​

创建学习库和账号,确认版本为 8.0.x;完成演示 SQL;重新连接后确认表仍然存在。

过关标准:能解释 MySQL 服务、连接参数、数据库、表、主键、外键和 ORM 分别是什么。