这是《MySQL 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 MySQL 是全球使用最广泛的开源关系型数据库之一。它负责保存系统中最关键的事实数据:用户、账户、订单、支付、库存、配置和审计记录。对大多数互联网业务来说,MySQL 不是“可以替换的存储组件”,而是数据一致性的最后防线。
本章帮助你建立 MySQL 的整体认知:它是什么,能解决什么问题,内部有哪些模块,和 Redis、Kafka、Elasticsearch 如何分工,以及学习 MySQL 时应该关注的重点。
1.1 为什么每个后端工程师都要懂数据库
一个典型的电商下单流程会涉及多个系统:
用户下单
-> 应用服务
-> MySQL:保存订单、扣减库存、记录支付状态
-> Redis:缓存商品详情、用户会话、热点计数
-> Kafka:发布订单事件
-> Elasticsearch:同步搜索索引和分析查询
如果 Redis 挂了,业务可能变慢;如果 Kafka 挂了,下游可能延迟;如果 MySQL 挂了,订单通常无法创建,已有数据的一致性也可能面临风险。
因此,MySQL 的核心价值是:
- 持久化:数据写入后可以长期保存;
- 事务:一组操作要么全部成功,要么全部失败;
- 一致性约束:主键、外键、唯一键和 CHECK 约束保证数据符合规则;
- 关系模型:用表和关系表达业务实体;
- SQL 接口:提供声明式查询和统一操作语言;
- 生态成熟:备份、复制、监控、迁移、云服务都有完整工具链。
1.2 MySQL 能做什么
常见场景:
| 场景 | 示例 | 关键能力 |
|---|---|---|
| 交易系统 | 订单、支付、账户 | ACID 事务 |
| 用户系统 | 账号、权限、资料 | 唯一约束、索引 |
| 商品系统 | SPU、SKU、库存 | 关系建模、行锁 |
| 审计日志 | 操作记录、资金流水 | 持久化、不可覆盖 |
| 配置管理 | 应用配置、开关 | 小规模高可用读写 |
| 报表辅助 | 低频统计查询 | SQL 聚合、窗口函数 |
MySQL 也常被用于不适合的场景:
| 不适合场景 | 原因 | 更合适的选择 |
|---|---|---|
| 秒级高频计数 | 每次都更新热点行 | Redis |
| 大规模全文搜索 | 倒排索引和分词能力有限 | Elasticsearch |
| 高吞吐事件流 | 不擅长 append-only 事件流 | Kafka |
| 海量 OLAP 扫描 | 行存和事务模型不是为分析设计 | ClickHouse |
| 超大文档存储 | JSON 不是无限扩展的文档库 | MongoDB / 对象存储 |
| 图查询 | 递归和关系遍历能力有限 | 图数据库 |
判断技术选型时,不要只问“能不能实现”,还要问“在这个场景下是否稳定、便宜、容易维护”。
1.3 MySQL 的整体架构
MySQL 可以分为 Server 层和存储引擎层。
Client
|
v
Connector 连接器、认证、权限
|
v
Server Layer
|-- Parser 词法/语法解析,生成 AST
|-- Preprocessor 语义检查、权限检查
|-- Optimizer 逻辑优化、物理优化、代价估算
|-- Executor 执行计划、调用存储引擎接口
|-- Query Cache 已移除,不应再作为学习重点
|-- Binlog Server 层归档/复制日志
+-- Utilities 管理工具、内置函数
|
v
Storage Engine Layer
|-- InnoDB 事务、MVCC、锁、Buffer Pool、Redo/Undo
|-- MyISAM 老引擎,表锁,不支持事务
|-- Memory 内存表,重启丢失
|-- CSV / Archive 特殊格式和归档场景
+-- Custom Engine 自定义引擎
1.3.1 Server 层
Server 层负责连接、解析、优化和执行 SQL。它不直接管理数据文件,而是通过存储引擎接口读写数据。
重要组件:
| 组件 | 职责 |
|---|---|
| Connector | 维护连接、认证身份、检查全局权限 |
| Parser | 把 SQL 文本解析为语法树 |
| Optimizer | 选择索引、JOIN 顺序、访问路径 |
| Executor | 按执行计划调用引擎接口 |
| Binlog | 记录逻辑变更,用于复制和恢复 |
1.3.2 存储引擎层
MySQL 的存储引擎是插件式的。现代互联网业务几乎默认使用 InnoDB。
InnoDB 的关键能力:
- ACID 事务;
- MVCC 多版本并发控制;
- 行级锁;
- B+Tree 聚簇索引;
- Buffer Pool 缓存;
- Redo Log 崩溃恢复;
- Undo Log 回滚和版本链;
- Change Buffer、Doublewrite Buffer、AHI 等优化机制。
SELECT ENGINE, SUPPORT, COMMENT
FROM information_schema.ENGINES;
1.4 InnoDB 表逻辑结构
一张 InnoDB 表逻辑上由表空间、段、区、页和行组成。
Tablespace
+-- Segment
+-- Extent
+-- Page / Block,默认 16KB
+-- Row
最重要的事实是:InnoDB 表本身就是按主键组织的 B+Tree,这种结构叫聚簇索引。
| 结构 | 说明 |
|---|---|
| 主键索引 | 叶子节点保存完整行数据 |
| 二级索引 | 叶子节点保存索引列和主键值 |
| 回表 | 通过二级索引找到主键,再查主键索引拿完整行 |
| 覆盖索引 | 查询字段都在索引中,不需要回表 |
这解释了为什么以下设计很重要:
- 尽量使用显式自增或趋势递增主键;
- 避免随机 UUID 作为主键导致页分裂;
- 二级索引不宜过多;
- 高频查询可以考虑覆盖索引;
- 大字段会影响聚簇索引行存储和内存效率。
1.5 一条 SQL 的执行流程
以查询为例:
SELECT order_id, user_id, amount
FROM orders
WHERE user_id = 10001
AND status = 'PAID';
执行流程:
1. 客户端发送 SQL
2. 连接器检查身份和权限
3. Parser 解析 SQL,生成语法树
4. 优化器评估可能索引和访问方式
5. Executor 按执行计划调用 InnoDB
6. InnoDB 从 Buffer Pool 或磁盘读取数据页
7. 根据索引结构定位记录
8. Server 层过滤、投影、返回结果
查看执行计划:
EXPLAIN
SELECT order_id, user_id, amount
FROM orders
WHERE user_id = 10001
AND status = 'PAID';
执行计划会在后续章节详细分析,本章只需建立整体印象:SQL 是声明式语言,MySQL 优化器会决定怎么执行,而工程师要通过表结构和索引影响它做正确选择。
1.6 MySQL 与其他系统的分工
现代后端通常是多个存储系统的组合:
| 系统 | 职责 | 数据一致性角色 |
|---|---|---|
| MySQL | 事实来源、事务、强一致 | 最终事实 |
| Redis | 缓存、热点计数、分布式锁 | 可重建的派生数据 |
| Kafka | 事件流、解耦、削峰 | 变更传播 |
| Elasticsearch | 搜索、日志、分析 | 可重建的查询投影 |
| ClickHouse | OLAP 分析 | 离线或实时分析副本 |
常见数据流:
MySQL
-> Binlog / CDC
-> Kafka
-> Redis 缓存更新
-> Elasticsearch 搜索索引
-> ClickHouse 分析表
这个架构的关键原则:
- MySQL 是事实来源;
- 派生存储可以丢失后重建;
- 缓存和搜索同步必须考虑乱序、重复和延迟;
- 业务不要依赖派生数据做资金判断;
- 对账任务应比较 MySQL 与下游数据。
1.7 MySQL 8.0 的重要变化
本书以 MySQL 8.0 为主线。相比 5.7,8.0 有很多实用改进:
| 特性 | 说明 |
|---|---|
| 默认 utf8mb4 | 默认字符集支持完整 Unicode |
| 默认事务隔离级别 RR | 5.7 也是 RR,8.0 继续保留 |
| CTE | WITH 语法 |
| 窗口函数 | ROW_NUMBER、RANK 等 |
| JSON 增强 | JSON 函数和索引能力增强 |
| 原子 DDL | DDL 变成原子操作 |
| 隐藏索引 | 测试索引删除影响 |
| 降序索引 | 真正支持降序存储 |
| Instant DDL | 部分变更秒级完成 |
| 数据字典改造 | 使用 InnoDB 存储元数据 |
| 角色管理 | 数据库权限更清晰 |
| EXPLAIN ANALYZE | 查看真实执行统计 |
如果生产仍使用 5.7,需要重点关注:
- 升级前的兼容性检查;
- 字符集和排序规则变化;
- 时区支持;
- JSON / CTE / 窗口函数不可用;
- 官方生命周期结束后的安全风险。
1.8 学习 MySQL 的五个层次
第一层:会使用
- 连接数据库;
- 编写 CRUD;
- 设计简单表;
- 使用基本索引;
- 看懂常见错误。
第二层:会优化
- 看懂执行计划;
- 设计联合索引;
- 处理慢查询;
- 分析锁等待;
- 控制大事务。
第三层:懂原理
- B+Tree;
- MVCC;
- Redo / Undo / Binlog;
- Buffer Pool;
- 两阶段提交;
- 行锁、间隙锁和死锁。
第四层:会治理
- 主从复制;
- 高可用;
- 备份恢复;
- 容量规划;
- 监控告警;
- 在线 DDL 和数据迁移。
第五层:懂架构和内核
- 大规模分库分表;
- 数据迁移和双写切流;
- 读写隔离和弹性扩展;
- 优化器行为;
- InnoDB 内部实现;
- 源码阅读与问题定位。
本书会按这个路径逐层展开。
1.9 生产视角的基本红线
以下是生产 MySQL 的常见红线:
- 不允许无 WHERE 条件的 UPDATE / DELETE;
- 不允许直接删除未知表;
- 不允许在业务高峰执行大 DDL;
- 不允许无备份上线重大变更;
- 不允许长期使用超级用户连接业务;
- 不允许主库随意跑分析大查询;
- 不允许所有查询都靠超时兜底;
- 不允许只靠人工备份而不演练恢复;
- 不允许忽略慢查询和锁等待;
- 不允许没有主从延迟和高可用监控。
这些规则看起来朴素,但大多数严重事故都来自其中一条被忽略。
1.10 一个最小业务表设计
订单表示例:
CREATE TABLE orders (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
order_no VARCHAR(32) NOT NULL COMMENT '业务订单号',
user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
merchant_id BIGINT UNSIGNED NOT NULL COMMENT '商户ID',
status VARCHAR(16) NOT NULL DEFAULT 'CREATED' COMMENT '订单状态',
total_amount DECIMAL(12, 2) NOT NULL DEFAULT 0.00 COMMENT '订单总金额',
paid_amount DECIMAL(12, 2) NOT NULL DEFAULT 0.00 COMMENT '实付金额',
currency CHAR(3) NOT NULL DEFAULT 'CNY' COMMENT '币种',
paid_at DATETIME(3) NULL COMMENT '支付时间',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
UNIQUE KEY uk_order_no (order_no),
KEY idx_user_created (user_id, created_at),
KEY idx_status_created (status, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
设计要点:
id是趋势递增主键;order_no使用唯一键表达业务约束;- 金额使用
DECIMAL,不用浮点; - 时间使用
DATETIME(3)保存毫秒; - 常用查询路径建立复合索引;
- 表和字段都有 COMMENT;
- 字符集统一
utf8mb4。
本章小结
MySQL 是后端系统的事实来源和事务防线。它由 Server 层负责解析、优化和执行,由 InnoDB 负责事务、锁、MVCC、缓存和持久化。InnoDB 表按主键组织的 B+Tree 结构决定了索引设计和主键选择的重要性。学习 MySQL 应从 SQL 和表设计开始,逐步进入执行计划、事务锁、复制高可用和生产治理。
思考题
- MySQL Server 层和 InnoDB 存储引擎层分别负责什么?
- 为什么 Redis、Elasticsearch、ClickHouse 通常不能替代 MySQL 的事务职责?
- 什么是聚簇索引?为什么二级索引可能需要回表?
- MySQL 8.0 有哪些对你当前业务有价值的新特性?
- 你们生产数据库有哪些必须固化的操作红线?