Learn
MySQL/01-introduction

MySQL 概览

💡🤖 AI 时代,还要学 MySQL 吗?学到什么程度?

必要且系统学。今天 AI 能替你写大部分 SQL 与建表语句,但 B+ 树索引、事务隔离级别、慢查询调优这些原理替代不了——它生成的 SQL 慢或出错时,你得能自己看出来并改对。语法和样板不必死记,用时让 AI 生成并人工核对即可;但数据模型与索引原理必须学到「能审 AI 的 SQL」的程度,否则系统一慢一错你就没了方向。

你可能已经会用 MySQL 做增删改查了,但当面试官问「一条 SELECT 语句在 MySQL 内部是怎么执行的」,或者线上出现慢查询、死锁时,只会 CRUD 就不够用了。本课程的目标是带你从「会用」走到「懂原理、能调优」。第一章先建立全局视野:MySQL 是什么、内部长什么样。

1. 关系型数据库的定位

数据库大致分两类:

类型代表特点适用场景
关系型(RDBMS)MySQL、PostgreSQL、Oracle表结构、SQL、事务(ACID)订单、账户、库存等强一致业务
非关系型(NoSQL)Redis、MongoDB、Elasticsearch灵活模型、高吞吐、最终一致缓存、日志、搜索、文档

关系型数据库的核心竞争力是事务:转账时「扣款」和「入账」要么都成功、要么都失败,这是 Redis 和 MongoDB(早期)做不到或做不好的。电商系统里用户、订单、支付这些核心数据几乎都放在 MySQL 里,缓存和搜索才交给 NoSQL。

MySQL 的市场地位来自三点:开源免费、生态成熟(几乎所有语言都有成熟驱动)、互联网大厂多年生产验证(配套的运维、高可用方案极其丰富)。

2. MySQL 架构分层

理解 MySQL,先记住这张分层图——后面讲索引、事务、锁时都会回到这里:

客户端 (mysql / JDBC / ORM)
        │
┌───────▼────────────────────────────┐
│  连接层                             │  ← 连接管理、认证、线程池
├────────────────────────────────────┤
│  Server 层                          │
│   ├─ 解析器(词法/语法分析)          │
│   ├─ 优化器(选索引、定 JOIN 顺序)   │
│   ├─ 执行器(调用存储引擎接口)        │
│   └─ binlog(归档日志,Server 层写)  │
├────────────────────────────────────┤
│  存储引擎层(插件式)                 │
│   ├─ InnoDB(默认:事务/行锁/崩溃恢复)│
│   ├─ MyISAM(老引擎:表锁/无事务)    │
│   └─ Memory / Archive ...           │
└────────────────────────────────────┘

2.1 连接层

负责 TCP 连接管理和用户认证。每个连接对应一个线程,show processlist 能看到所有连接。连接建立成本不低,所以生产应用一定用连接池(第 21 章细讲)。

2.2 Server 层

一条 SQL 到达后依次经过:

  1. 解析器:检查语法,把 SQL 文本变成解析树。写错关键字时报的 You have an error in your SQL syntax 就来自这里。
  2. 优化器:决定用哪个索引、多表 JOIN 用什么顺序。它是「基于成本」的——估算每种执行方式要扫多少行,选最便宜的。优化器估错时就会出现「明明有索引却不走」的经典问题(第 14 章讲 EXPLAIN 时会分析)。
  3. 执行器:按优化器给出的计划,一行行调用存储引擎的接口取数据、过滤、返回。

2.3 存储引擎层

真正管「数据怎么存、怎么读」的一层,以插件形式存在。同一个库里不同表可以用不同引擎——但生产上几乎只用 InnoDB。

3. InnoDB vs MyISAM

MySQL 5.5 之后 InnoDB 是默认引擎。两者对比:

能力InnoDBMyISAM
事务支持(ACID)不支持
锁粒度行级锁表级锁
崩溃恢复支持(redo log)不支持,易损坏
外键支持不支持
索引结构聚簇索引(数据即索引)非聚簇(索引与数据分离)
COUNT(*) 无条件需要扫描直接读元数据,O(1)

结论很简单:新表一律用 InnoDB。MyISAM 唯一的「优势」(无条件 COUNT 快、占用略小)在现代业务里完全不值得用崩溃安全和事务去换。

查看版本与存储引擎
SELECT VERSION();
 
-- 查看当前支持的引擎
SHOW ENGINES;
 
-- 查看各张表用的引擎
SELECT table_name, engine, table_rows
FROM information_schema.tables
WHERE table_schema = 'shop';

在 mysql 客户端里还可以用 SHOW TABLE STATUS LIKE 'users'\G 竖排查看单表的引擎与统计信息。

ℹ️为什么 InnoDB 的 COUNT(*) 慢?

InnoDB 支持 MVCC(多版本并发控制),不同事务在同一时刻看到的行数可能不同,所以没法维护一个全局计数器,只能真的去数。第 17 章讲 MVCC 时你会彻底理解这一点。

4. 一条 SQL 的完整旅程

以 SELECT * FROM users WHERE id = 10; 为例:

1. 连接层:校验用户权限,接收 SQL
2. 解析器:确认语法合法,识别出表名 users、条件 id = 10
3. 优化器:发现 id 是主键,决定走主键索引
4. 执行器:调用 InnoDB 接口「按主键取 id=10 的行」
5. InnoDB:先查 Buffer Pool(内存缓存),命中直接返回;
   未命中则从磁盘读入 16KB 数据页再返回
6. 执行器:把行返回给客户端

其中第 5 步的 Buffer Pool 是 InnoDB 性能的核心:数据以 16KB 的「页」为单位缓存在内存里,绝大多数读请求根本不碰磁盘。

💡MySQL 8.0 移除了查询缓存

老版本有 Query Cache(缓存 SQL 到结果的映射),但表一有更新缓存就全部失效,命中率极低还引发锁竞争,8.0 彻底删掉了。需要缓存请在应用层用 Redis 做。

5. 版本选择

版本状态说明
5.72023-10 已 EOL大量存量系统还在用,新项目不要选
8.0主流 LTS本课程基准:窗口函数、CTE、原子 DDL、默认 utf8mb4
8.4 / 9.x新 LTS / 创新版8.4 是下一代 LTS,9.x 为快速迭代的创新版本

8.0 相比 5.7 的关键改进(本课程都会讲到):

  • 窗口函数与 CTE(第 10、11 章):复杂分析查询不再需要变量黑魔法
  • 原子 DDL:建表/改表要么完全成功要么完全回滚,不再出现「表建了一半」
  • 默认字符集 utf8mb4:原生支持 emoji
  • 降序索引、函数索引、不可见索引(第 13 章)
  • EXPLAIN ANALYZE(第 14 章):看真实执行耗时而不只是估算
⚠️不要在生产使用 5.7

MySQL 5.7 已于 2023 年 10 月停止官方支持,不再有安全补丁。存量系统应规划升级到 8.0/8.4。

6. 贯穿全课程的电商示例库

从第 3 章开始,我们会围绕一套电商库练习,包含五张表:

users        用户表
categories   商品分类(支持父子层级)
products     商品表
orders       订单表
order_items  订单明细(订单与商品的多对多桥表)

关系:一个用户有多个订单,一个订单包含多条明细,每条明细指向一个商品,每个商品属于一个分类。这套结构覆盖了一对多、多对多、自关联等所有常见建模场景,后面讲 JOIN、索引、事务、优化时全部基于它。

本课程的 Playground 已经预置了这套 shop 库,先认识一下:

认识电商示例库
SHOW TABLES;
 
DESC users;
 
SELECT * FROM users;
SELECT id, category_id, name, price, stock, status FROM products;
SELECT id, order_no, user_id, status, total_amount, created_at FROM orders;
ℹ️Playground 说明

在线执行环境用的是 MySQL 兼容的 MariaDB 11,默认库就是 shop,每次运行都是一个全新的一次性容器——写操作(INSERT/UPDATE/DELETE 甚至 DROP)不会影响下一次运行,放心大胆地试。

小结

  • MySQL 分三层:连接层管连接,Server 层负责解析/优化/执行,存储引擎层管数据存取
  • 生产一律用 InnoDB:事务、行锁、崩溃恢复缺一不可
  • Buffer Pool 是性能核心,绝大多数读写发生在内存
  • 版本选 8.0(或 8.4 LTS),5.7 已停止维护
🎯练习
  1. 用你手边任何一个 MySQL 实例执行 SELECT VERSION(); 和 SHOW ENGINES;,确认版本与默认引擎。
  2. 执行 SHOW VARIABLES LIKE 'innodb_buffer_pool_size';,把结果换算成 MB,思考它相对机器内存的占比是否合理(专用数据库服务器通常设为物理内存的 50%–70%)。
  3. 口述一遍:一条 SELECT 从客户端发出到返回结果,经过了哪些组件?