入门:MySQL 定义、InnoDB 引擎与索引事务
基于 MySQL 8.4 LTS / 9.x · 核于 2026-08
速查
- 定义:MySQL 是开源关系型数据库,用 SQL 把数据组织成表(行+列),以行式存储 + B+ 树索引 + ACID 事务为核心,是 OLTP 事实标准。本站 quiz-backend 跑在它上面。
- 版本:8.4 LTS(2024,长期支持到 2032,生产首选);9.x(创新版,加向量、JS 存储过程,迭代快但非 LTS)。新项目选 8.4 LTS。
- 架构分层:server 层(连接器/解析器/优化器/执行器,跨引擎共享)+ 存储引擎层(InnoDB/MyISAM,真正存取数据)。
CREATE TABLE ... ENGINE=InnoDB选引擎。 - InnoDB:默认引擎,行锁 + MVCC + 崩溃恢复(redo log)+ 外键,事务安全。MyISAM 已基本淘汰(表锁、不支持事务)。
- B+ 树索引:所有数据存叶子节点(构成有序链表,范围查询快),非叶子节点只存键值(扇出大、树矮,3-4 层就能存亿级行)。innodb_buffer_pool 缓存热数据与索引。
- 聚簇索引 vs 二级索引:InnoDB 主键索引即聚簇索引(叶子存整行数据);二级索引叶子存主键值,查二级索引要回主键索引取数据(回表),除非覆盖索引(索引含查询所需全部列)。
- ACID:原子性(undolog 回滚)、一致性、隔离性(锁+MVCC)、持久性(redolog 刷盘)。默认隔离级别 REPEATABLE READ(可避免脏读/不可重复读/幻读,靠间隙锁)。
- MVCC:多版本并发控制——每行有版本链(undo log),读不加锁看快照(一致性视图),写加行锁。解决读写冲突,是高并发基础。
- 复制:主库写 binlog → 从库 IO 线程拉 → 写 relay log → SQL 线程回放。GTID(全局事务 ID)让复制追踪与故障切换更可靠。半同步/组复制(MGR)提升一致性。
- JSON:8.0 起原生 JSON 类型(二进制存储,可校验),
->/->>操作、JSON_EXTRACT/JSON_TABLE函数——半结构化数据也能放进关系库。 - 连接池:应用侧(HikariCP/Prisma 内置)复用连接,避免每次 TCP+鉴权握手;
max_connections(默认 151)要按「连接池上限 × 实例数」估算。 - EXPLAIN:分析 SQL 执行计划——
type(访问类型,const/ref/range/index/ALL,ALL是全表扫描要避)、key(实际用的索引)、rows(预估扫描行数)、Extra(Using index是覆盖索引好事,Using filesort/Using temporary是坏事)。 - 进阶顺序:InnoDB 引擎与索引事务 → 复制、JSON 与性能调优 → 参考。
一、MySQL 是什么:开源关系库的事实标准
MySQL 用 SQL 把数据组织成表——每行一条记录,每列有固定类型(INT/VARCHAR/DATETIME/JSON)。表与表通过外键或应用层逻辑建立关联(hence「关系型」)。它的核心承诺是 ACID:事务要么全做要么全不做(原子性),数据从一个合法状态转到另一个(一致性),并发事务互不干扰(隔离性),提交后断电也不丢(持久性)。
- 为什么是「事实标准」:30 年沉淀 + LAMP/LNMP 架构普及 + 云厂商托管(AWS RDS、阿里云 RDS/PolarDB、腾讯云 TDSQL)+ 运维资料最全 + 招人最容易。WordPress/维基百科/淘宝早期都跑在 MySQL。
- 本站实践:
apps/quiz-backend用 Prisma 7 + MySQL(MariaDB 适配器),.env.production.local配 RDS 连接,import:content:prod把题目灌进生产库——你正在做的三件套就存这里。 - 竞品定位:PostgreSQL 功能更强(JSONB/扩展生态)但生态略小;SQLite 嵌入式零运维但不能高并发;Oracle/SQL Server 商业闭源收费。MySQL 在「成熟稳定 + 生态丰富 + 中等复杂度 OLTP」这个甜区统治。
二、版本选择:8.4 LTS vs 9.x
| 版本 | 定位 | 关键特性 | 建议 |
|---|---|---|---|
| 8.4 LTS(2024) | 长期支持版,支持到 2032 | 窗口函数、CTE、JSON 增强、不可见索引、降序索引、并行查询改进 | 生产首选 |
| 8.0(2019) | 上一代主流 | 默认 utf8mb4、事务数据字典、角色权限 | 老项目维护 |
| 9.x(2024+) | 创新版,迭代快 | VECTOR 类型(AI 向量)、JavaScript 存储过程、事务采样 | 尝鲜,不建议上生产 |
| 5.7 | 已 EOL(2023) | — | 必须升级 |
新项目无脑选 8.4 LTS——长期支持、bug 修复有保障、云厂商跟进最快。9.x 的向量类型虽然诱人,但生产稳定性与生态(Driver/ORM 适配)尚需时间。
三、架构分层:server 层与存储引擎
MySQL 把功能分成两大层,理解这个分层是理解一切调优的前提:
客户端(JDBC/Prisma/mysql CLI)
│ TCP(连接器鉴权 + 线程)
═══════════════╪═══════════════════════
┌───────┴────────┐
│ server 层 │ ← 跨引擎共享
│ ├ 连接器 │ 所有引擎走同一套
│ ├ 解析器(AST)│
│ ├ 优化器(成本)│ ← 选索引、定 JOIN 顺序
│ └ 执行器 │ 调引擎接口取数据
└───────┬────────┘
═══════════════╪═══════════════════════ 引擎接口(handler API)
┌───────┴────────┐
│ 存储引擎层 │ ← 真正存取数据
│ InnoDB(默认)│ 文件系统之上的存储抽象
│ MyISAM/NDB │
└────────────────┘
磁盘(ibd 文件)- server 层管「连接、解析、优化、执行」,与引擎无关——所以
EXPLAIN、慢查询日志、binlog 都在 server 层。 - 存储引擎层管「数据怎么存、用什么索引、怎么加锁」。
CREATE TABLE ... ENGINE=InnoDB选引擎,95% 场景用 InnoDB。MyISAM 不支持事务/行锁/外键,已基本淘汰。 - 优化器是关键:它基于统计信息估算成本,选索引和 JOIN 顺序。统计过期会导致选错索引——
ANALYZE TABLE可刷新。
四、InnoDB:默认引擎的四大支柱
InnoDB 之所以成为默认引擎,靠四件事:
- 行锁 + MVCC:读不加锁(看快照),写只锁命中的行——高并发下读写互不阻塞,是 OLTP 高吞吐基础。
- 崩溃恢复:用 redo log(重做日志)保证提交的事务断电不丢(持久性),用 undo log(回滚日志)保证未提交的事务可回滚(原子性)。WAL(Write-Ahead Logging)——先写日志再改数据页,是数据库持久性的通用套路。
- 外键约束:跨表引用完整性,父表删/改时自动检查或级联。
- 聚簇索引:主键索引与数据一体存储(叶子节点就是整行),按主键查询极快,也利于范围扫描。
innodb_buffer_pool 是 InnoDB 最重要的参数——缓存热数据页与索引页的内存区,通常设为可用内存的 50-70%。命中率应 > 99%,否则性能急剧下降。
五、索引:B+ 树与聚簇/二级
MySQL 索引的底层数据结构是 B+ 树(不是 B 树、不是红黑树):
- B+ 树特点:所有数据只在叶子节点,非叶子节点只存键值用于路由;叶子节点用双向链表串成有序序列。
- 为何高效:①扇出大(一个节点存几百个键),3-4 层就能存亿级行,点查 3-4 次磁盘 IO;②范围查询顺着叶子链表扫即可,无需回溯。
InnoDB 的索引分两类:
| 类型 | 内容 | 查询 |
|---|---|---|
| 聚簇索引(主键索引) | 叶子节点存整行数据 | 按主键查,一次定位 |
| 二级索引(非主键索引) | 叶子节点存主键值 + 索引列 | 按二级索引查到主键,再回表到聚簇索引取整行 |
- 回表(lookup):二级索引查到主键后,再去聚簇索引取完整行——多一次 IO。覆盖索引(索引包含查询所需的全部列)可避免回表,
EXPLAIN里看到Using index就是覆盖索引,是好事。 - 联合索引最左前缀:
INDEX(a, b, c)能用于WHERE a=?、a=? AND b=?、a=? AND b=? AND c=?,但不能用于WHERE b=?(跳过了 a)。索引列顺序按区分度高、查询频繁、常作范围排。
六、事务与隔离级别
事务是一组操作「要么全做要么全不做」的单元。MySQL 用 ACID 保证:
- 原子性(A):靠 undo log,失败回滚。
- 持久性(D):靠 redo log + WAL,提交即落盘。
- 隔离性(I):靠锁(写)+ MVCC(读)。
- 一致性(C):AID 共同保证。
四种隔离级别(从弱到强):
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
|---|---|---|---|---|
| READ UNCOMMITTED | 可能 | 可能 | 可能 | 最高 |
| READ COMMITTED(PG 默认) | 避免 | 可能 | 可能 | 高 |
| REPEATABLE READ(MySQL 默认) | 避免 | 避免 | 避免(间隙锁) | 中 |
| SERIALIZABLE | 避免 | 避免 | 避免 | 最低 |
- MySQL 默认 REPEATABLE READ,靠 MVCC(一致性视图)避免不可重复读,靠间隙锁/临键锁避免幻读——这点比其他数据库(如 Oracle/PG 在 RR 下仍有幻读)更严格。
- MVCC(多版本并发控制):每行在 undo log 里有历史版本链。事务开始时生成「一致性视图」(看到哪些版本),读操作不加锁看快照——所以读写不冲突。代价是长事务会让 undo 膨胀、purge 线程跟不上、空间无法回收。
七、复制与高可用:binlog 与 GTID
MySQL 主从复制是高可用与读写分离的基础:
- binlog(归档日志):server 层记录所有已提交的数据变更(DDL+DML),主要用于复制与 PITR(按时间点恢复)。三种格式:
STATEMENT(记 SQL,小但非确定函数可能不一致)、ROW(记每行变更,大但确定,默认)、MIXED。 - 复制流程:主库写 binlog → 从库 IO 线程拉取 → 写 relay log → SQL 线程回放 relay log → 数据一致。
- GTID(全局事务 ID):每个事务有
<server_uuid>:<seq>唯一标识,从库自动对齐已应用的事务——故障切换不再手动找 binlog 位点,是现代复制标配。 - 半同步复制:主库等至少一个从库收到 binlog 才返回提交成功,比异步复制少丢数据。
- 组复制(MGR):基于 Paxos 的多主一致性集群,配合 MySQL Router 实现 InnoDB Cluster 高可用。
八、JSON、连接池与 EXPLAIN 调优
- JSON 类型(8.0+):原生二进制存储 + 自动校验。
col->'$.key'取值,col->>'$.key'取文本,JSON_EXTRACT/JSON_SET/JSON_TABLE操作。半结构化数据(如配置、标签)不必再拆表或塞TEXT手解析。 - 连接池:每次新建 MySQL 连接要 TCP 握手 + 鉴权 + 权限加载,开销大。连接池(应用侧 HikariCP、Prisma 内置、服务端 ProxySQL)复用连接。
max_connections(默认 151)× 单连接内存 ≈ 总内存,要按实例数估算,别撑爆。 - EXPLAIN:在 SQL 前加
EXPLAIN看执行计划。重点字段:type:访问类型,从好到坏const>eq_ref>ref>range>index>ALL(全表扫描,要消灭)。key:实际选用的索引(NULL 表示没用索引)。rows:预估扫描行数,越小越好。Extra:Using index(覆盖索引,好)、Using where(过滤)、Using filesort/Using temporary(额外排序/临时表,要优化)。
- 慢查询日志:
slow_query_log=ON+long_query_time=1,记录执行超过 1 秒的 SQL,是定位性能问题的第一手段。
下一步
理解了 MySQL 的全貌后,下一步深入两个核心——InnoDB 引擎与索引事务(B+ 树内部、聚簇/二级索引、MVCC 与锁机制)与复制、JSON 与性能调优(binlog/GTID/半同步、JSON 函数、EXPLAIN 实战与慢查询分析)。