Skip to content

MySQL

MySQL 是常用的关系型数据库。学习 MySQL 不能只停留在“会写 selectinsert”,还要理解数据是怎么存的、索引为什么能加速、事务为什么能保证一致性、锁为什么会阻塞、慢 SQL 为什么会慢。

零基础可以先抓住一句话:

MySQL 的本质是:把结构化数据按表保存起来,并在并发访问时尽量做到“查得快、写得对、坏了能恢复”。

学 MySQL 要解决什么问题

问题MySQL 对应能力如果不会会怎样
数据怎么长期保存表、字段、数据类型、约束数据格式混乱,后期无法维护
查询为什么有快有慢索引、执行计划、优化器慢 SQL 只能靠猜,容易乱加索引
多人同时改数据怎么办事务、锁、MVCC出现超卖、丢失更新、脏数据
数据库异常后怎么恢复redo log、undo log、binlog无法解释提交、回滚和主从同步
数据量大了怎么办分页、归档、索引治理、架构治理表越来越慢,系统容量不可控

学习路线

mermaid
flowchart TD
    A["SQL 基础"] --> B["表设计"]
    B --> C["查询与 Join"]
    C --> D["架构分层"]
    D --> E["存储结构和 Buffer Pool"]
    E --> F["索引和 B+Tree"]
    F --> G["EXPLAIN 和优化器"]
    G --> H["事务 / 锁 / MVCC"]
    H --> I["日志 / 主从 / 备份"]
    I --> J["大表治理 / 分库分表 / 面试"]

推荐阅读顺序:

  1. 知识地图与 7 天速学路线:先建立全局坐标,按面试时间选择学习路径。
  2. SQL 基础:先学会增删改查、分页、条件、逻辑执行顺序。
  3. SQL 进阶:掌握聚合、窗口函数、CTE、子查询、NULL 和稳定分页。
  4. 安装、连接与核心配置:理解版本、参数作用域、连接和内存预算。
  5. 字符集、排序规则与时区:解决乱码、比较规则和跨时区问题。
  6. JSON、生成列与数据库对象:补齐 JSON 索引、全文检索、视图、触发器等能力边界。
  7. 从零到生产级掌握:把表设计、索引、执行计划、事务、日志、主从和排查连成课程线。
  8. 从零到精通验收清单:用可验证任务判断自己是不是真的会了,而不是只看过概念。
  9. 商业场景训练营:用订单支付、库存、大表、锁、死锁、主从延迟把理论跑起来。
  10. 表设计:理解字段类型、主键、唯一约束、宽表窄表和反范式。
  11. 查询与 Join:理解 Join、子查询、N+1、连接字段索引。
    • 复杂关联查询实战:掌握一对多放大、预聚合、半/反连接、时态 Join、父子分页和财务核对。
  12. MySQL 架构分层:理解连接层、Server 层、存储引擎层分别负责什么。
  13. MySQL 架构分层与请求全过程:把三层、五层、select、update、日志边界和排查分层讲透。
  14. SQL 执行全过程原理:把连接、解析、优化器、执行器、InnoDB 读页、回表、排序完整串起来。
  15. 存储引擎与 Buffer Pool:理解 InnoDB、缓存页、脏页、刷盘。
  16. 存储结构:理解 InnoDB 为什么用页、B+Tree、聚簇索引。
  17. B+Tree、B-Tree 与数据库索引家族:讲清 MySQL 为什么用 B+Tree,以及 Oracle、PostgreSQL、SQL Server 为什么常说 B-Tree。
  18. 索引知识点:学习最左前缀、覆盖索引、回表、索引失效。
  19. EXPLAIN:学会看执行计划,并理解 typekeykey_lenrowsfilteredExtra 这些字段从哪里来。
  20. 优化器原理:理解为什么有索引不一定用、统计信息怎么影响执行计划。
  21. 事务:理解 ACID、隔离级别、提交和回滚。
  22. :理解行锁、间隙锁、临键锁、死锁。
  23. MVCC:理解快照读为什么能做到读写不互相阻塞,以及 undo log 如何提供旧版本。
  24. redo log 与 binlog:理解崩溃恢复、主从复制、两阶段提交。
  25. InnoDB 更新事务全过程原理:把行锁、undo、Buffer Pool、redo、binlog、两阶段提交、MVCC 完整串起来。
  26. 主从复制:理解 binlog 复制、读写分离、主从延迟。
  27. 备份恢复:理解全量备份、binlog 时间点恢复、误删恢复流程。
  28. 大表覆盖索引仍然慢:理解覆盖索引无法解决扫描大、深分页、冷热数据等问题。
  29. 分库分表:理解容量治理、分片键、跨分片问题。
  30. Apache ShardingSphere:掌握 JDBC/Proxy、路由内核、分片配置、事务、迁移和排障。
  31. MySQL 高级:把执行计划、锁、事务、慢 SQL 排查串起来。
  32. 分区、归档与在线 DDL:理解分区裁剪、MDL 和大表结构变更。
  33. 安全与权限:掌握最小权限、SQL 注入、TLS、备份与敏感数据治理。
  34. 监控与故障排查:建立慢 SQL、连接、锁、IO 和磁盘故障的证据链。
  35. 高可用与容灾:理解 RPO/RTO、故障切换、脑裂和演练。
  36. MySQL 面试:学习重点题的标准回答与追问路径。
  37. 100 道高频面试题库:分层口述、自测,再训练 10 道生产场景题。

一条 SQL 的执行流程

mermaid
flowchart TD
    A["客户端发送 SQL"] --> B["连接器<br/>认证 / 权限 / 连接管理"]
    B --> C["解析器<br/>词法分析 / 语法分析"]
    C --> D["预处理<br/>检查表和字段是否存在"]
    D --> E["优化器<br/>选择索引 / 选择连接顺序"]
    E --> F["执行器<br/>调用存储引擎接口"]
    F --> G["InnoDB<br/>读页 / 查索引 / 加锁"]
    G --> H["返回结果给客户端"]

这条链路里最容易出问题的是优化器和存储引擎:

环节初学者常见误解正确理解
解析器SQL 能写出来就一定高效语法正确只代表能执行,不代表执行代价低
优化器有索引就一定用索引优化器会估算成本,认为全表扫描便宜时可能不用索引
执行器查询就是从表里取几行实际可能要扫描大量索引页、回表、排序、临时表
InnoDB数据是一行一行读磁盘和 Buffer Pool 通常以页为单位读写

InnoDB 要同时解决三件事

mermaid
flowchart TD
    A["InnoDB"] --> B["性能<br/>B+Tree / Buffer Pool / 索引"]
    A --> C["并发<br/>事务 / 锁 / MVCC"]
    A --> D["可靠<br/>redo log / undo log / 崩溃恢复"]

如果只学 SQL,不学 InnoDB,很容易出现这些问题:

  1. 看到慢 SQL 只会加单列索引,不知道联合索引顺序怎么设计。
  2. 遇到死锁只会重启服务,不知道锁加在索引上。
  3. 不理解为什么普通 select 不阻塞 update,但 select ... for update 会阻塞。
  4. 不知道长事务为什么会导致 undo log 堆积。
  5. 不知道为什么自增主键比随机 UUID 更适合 InnoDB 聚簇索引。

SQL Demo:从建表到看执行计划

准备一张用户表:

sql
create table users (
  id bigint primary key auto_increment,
  username varchar(50) not null,
  status tinyint not null default 1,
  created_at datetime not null,
  updated_at datetime not null,
  unique key uk_username (username),
  key idx_status_created_at (status, created_at)
) engine = InnoDB default charset = utf8mb4;

插入数据:

sql
insert into users(username, status, created_at, updated_at)
values
  ('tom', 1, now(), now()),
  ('jerry', 1, now(), now()),
  ('bob', 0, now(), now());

查询启用用户:

sql
select id, username
from users
where status = 1
order by created_at desc
limit 20;

查看执行计划:

sql
explain
select id, username
from users
where status = 1
order by created_at desc
limit 20;

观察重点:

字段应该怎么看
key是否使用 idx_status_created_at
type是否避免了大表 ALL 全表扫描
rows预估扫描行数是否明显小于总行数
Extra是否出现 Using filesortUsing temporary

学习 MySQL 时要养成一个习惯:写完高频 SQL 后,必须用 EXPLAIN 验证执行计划。如果只看 SQL 语法,不看执行计划,很难发现线上慢 SQL。

高频知识点速查

知识点你要能讲清楚什么
B+Tree为什么适合范围查询,为什么树高低能减少 IO
聚簇索引为什么主键叶子节点就是整行数据
二级索引为什么查询非索引列可能回表
联合索引为什么要遵守最左前缀
覆盖索引为什么只查索引字段可以减少回表
事务隔离为什么不同隔离级别看到的数据不同
MVCC为什么普通查询可以读历史版本
行锁为什么 InnoDB 行锁加在索引记录上
间隙锁为什么 RR 下范围查询可能锁住不存在的数据
redo log为什么提交后宕机还能恢复
undo log为什么事务能回滚,快照读能看旧版本
binlog为什么主从同步和数据恢复依赖它

常见学习误区

误区问题正确做法
SQL 能查出来就行数据量小看不出性能问题建表阶段就考虑高频查询和索引
每个字段都建索引写入变慢,空间变大,优化器选择变复杂根据真实 SQL 设计联合索引
慢 SQL 一定是没索引也可能是返回太多、排序、锁等待、网络慢结合 EXPLAIN、慢日志和监控定位
事务越大越安全长事务持锁久,undo 堆积,阻塞清理事务只包住必须原子的一小段逻辑
只背隔离级别定义遇到 RC、RR 行为差异仍然不会分析结合 Read View 和当前读理解

最小练习路线

  1. 建一张表,包含主键、唯一索引、普通联合索引。
  2. 写 5 条查询 SQL,用 EXPLAIN 看是否使用索引。
  3. 故意写一个索引失效 SQL,例如 where date(created_at) = ?,观察执行计划变化。
  4. 开两个 MySQL 会话,模拟事务 A 更新不提交,事务 B 更新同一行等待。
  5. 在 RR 隔离级别下模拟 MVCC,观察普通 selectselect ... for update 的差异。

这些练习做完后,再去看锁、MVCC、redo/undo/binlog,会更容易把概念和现象对应起来。