MySQL 核心知识梳理:从底层原理到实战优化

MySQL 核心知识梳理:从底层原理到实战优化

  • [MySQL 核心知识梳理:从底层原理到实战优化](#MySQL 核心知识梳理:从底层原理到实战优化)
    • [1. MySQL 整体架构](#1. MySQL 整体架构)
    • [2. InnoDB 存储引擎(目前默认,也是重点)](#2. InnoDB 存储引擎(目前默认,也是重点))
    • [3. Buffer Pool ------ InnoDB 的内存加速器](#3. Buffer Pool —— InnoDB 的内存加速器)
    • [4. 日志系统:Redo Log vs Binlog](#4. 日志系统:Redo Log vs Binlog)
      • [4.1 Redo Log(重做日志,引擎层)](#4.1 Redo Log(重做日志,引擎层))
      • [4.2 Binlog(归档日志,Server 层)](#4.2 Binlog(归档日志,Server 层))
      • [4.3 为什么要两个日志?](#4.3 为什么要两个日志?)
    • [5. 索引](#5. 索引)
      • [5.1 B+ 树索引(InnoDB 默认)](#5.1 B+ 树索引(InnoDB 默认))
      • [5.2 自适应哈希索引(AHI)](#5.2 自适应哈希索引(AHI))
      • [5.3 其他索引](#5.3 其他索引)
      • 索引使用原则(面试高频)
    • [6. 事务与隔离级别](#6. 事务与隔离级别)
    • [7. MVCC(多版本并发控制)](#7. MVCC(多版本并发控制))
    • [8. 锁机制](#8. 锁机制)
      • [8.1 锁粒度](#8.1 锁粒度)
      • [8.2 锁类型](#8.2 锁类型)
      • [8.3 死锁](#8.3 死锁)
    • [9. SQL 优化实战(常见思路)](#9. SQL 优化实战(常见思路))
      • [9.1 慢查询定位](#9.1 慢查询定位)
      • [9.2 索引失效场景](#9.2 索引失效场景)
      • [9.3 分页优化](#9.3 分页优化)
      • [9.4 写优化](#9.4 写优化)
    • [10. 常用运维与监控](#10. 常用运维与监控)
    • 写在最后

MySQL 核心知识梳理:从底层原理到实战优化

一篇尽量系统但不说废话的 MySQL 知识地图,帮助你理解它为什么快、怎么保证不丢数据、以及如何写出高效的 SQL。


1. MySQL 整体架构

MySQL 分为 Server 层存储引擎层,这种分层设计让它支持多种存储引擎(InnoDB、MyISAM、Memory 等)。

复制代码
客户端连接
    ↓
连接器(管理连接、权限验证)
    ↓
查询缓存(8.0 已移除)→ 解析器(词法/语法分析)→ 优化器(选择索引、决定 join 顺序)→ 执行器(调用存储引擎接口)
    ↓
存储引擎(默认 InnoDB)
    ↓
磁盘文件(.ibd、.frm、binlog、redo log 等)
  • Server 层:负责连接管理、查询解析、优化、执行,以及 binlog、慢查询日志等。
  • 引擎层:负责数据的实际存储与读取,提供 ACID 事务、行锁、MVCC 等特性。

2. InnoDB 存储引擎(目前默认,也是重点)

InnoDB 是一个兼顾高可靠和高性能的通用存储引擎,适用于绝大多数 OLTP 场景。

核心特性

  • ACID 事务:支持原子性、一致性、隔离性、持久性。
  • 行级锁:默认使用行锁,并发性能远高于表锁。
  • 多版本并发控制(MVCC):实现非阻塞读,读写不冲突。
  • 外键约束:保证数据完整性。
  • Crash Safe:崩溃自动恢复(通过 Redo Log 和 Undo Log)。
  • 聚簇索引:数据和主键索引存储在一起,二级索引回表。

物理存储结构(了解即可)

  • 表空间(Tablespace) :逻辑存储单元,包括系统表空间、独立表空间(.ibd)、通用表空间等。
  • 段(Segment):数据段、索引段、回滚段。
  • 区(Extent):1 区 = 64 个连续页(默认 1MB)。
  • 页(Page):默认 16KB,是 InnoDB 读写的最小单位。

3. Buffer Pool ------ InnoDB 的内存加速器

Buffer Pool 是 InnoDB 的 内存核心,所有的数据读写优先经过它。

  • 作用:缓存磁盘上的数据页(包含表数据、索引、插入缓冲、自适应哈希索引等)。
  • 加速原理:读 -- 先从 Buffer Pool 命中,否则从磁盘读取并缓存;写 -- 先修改 Buffer Pool 中的页,标记为"脏页",后台线程择机刷盘。
  • 数据结构
    • free list:空闲页
    • LRU list:已被使用的页,采用 改进 LRU(分成 young 区和 old 区,防止全表扫描污染缓存)
    • flush list:脏页列表,按修改时间排序
  • 配置建议innodb_buffer_pool_size 设为服务器物理内存的 50%~75%;高并发下可设置 innodb_buffer_pool_instances 拆分成多个实例以降低争用。

4. 日志系统:Redo Log vs Binlog

4.1 Redo Log(重做日志,引擎层)

  • 记录内容:物理日志,例如 "在表空间 X、页号 Y、偏移量 Z 处将值 A 改成 B"。
  • 写入方式:固定大小、循环写入(写满后会覆盖旧的日志)。
  • 作用 :保证事务的持久性,即 Crash-Safe 能力。事务提交时,Redo Log 先行落盘,即使宕机,重启后也能根据 Redo Log 重放未完成的页修改。
  • 相关参数innodb_log_file_sizeinnodb_log_files_in_group

4.2 Binlog(归档日志,Server 层)

  • 记录内容 :逻辑日志,例如 UPDATE t SET c = c+1 WHERE id = 1
  • 写入方式:追加写,文件写满后切换下一个文件,不会覆盖。
  • 作用
    • Point-in-Time 恢复:利用 binlog 回放恢复到任意时刻。
    • 主从复制:从库订阅主库的 binlog 实现数据同步。
  • 格式:STATEMENT(记录 SQL)、ROW(记录行变更,推荐)、MIXED。

4.3 为什么要两个日志?

  • 早期 MySQL 默认引擎 MyISAM 没有 Crash-Safe 能力,靠 binlog 无法恢复。
  • InnoDB 加入后,为了实现自己的崩溃恢复,引入了 Redo Log;同时为了兼容 binlog 的复制/恢复机制,保留两者。
  • 两阶段提交 :保证 Redo Log 和 Binlog 逻辑一致,避免主从数据不一致。过程:
    1. Prepare:Redo Log 写入并标记为 prepare 状态。
    2. Commit:Binlog 写入成功 → 将 prepare 的 Redo Log 改为 commit 状态。

5. 索引

5.1 B+ 树索引(InnoDB 默认)

  • 聚簇索引(主键索引):叶子节点存储完整行数据
  • 二级索引(辅助索引):叶子节点存储主键值,查询数据需要"回表"。
  • 为什么用 B+ 树?
    • 矮胖:树高通常 3~4 层,适合磁盘 IO。
    • 叶子节点双向链表,支持范围扫描。
    • 非叶子节点只存索引,一个页可放更多键。

5.2 自适应哈希索引(AHI)

  • InnoDB 自动为热点索引页在内存中构建哈希索引,只针对等值查询
  • 优点:O(1) 定位,比 B+ 树更快。
  • 缺点:消耗内存、高并发下可能有争用。
  • 参数:innodb_adaptive_hash_index(默认 ON)。

5.3 其他索引

  • 全文索引:MATCH AGAINST 支持,适用于文本搜索。
  • 空间索引:用于地理数据(GIS)。

索引使用原则(面试高频)

  • 最左前缀原则 :联合索引 (a,b,c),查询条件必须从 a 开始,才能用到该索引。
  • 覆盖索引:select 的字段都在索引中,可避免回表。
  • 索引下推(ICP):在索引遍历过程中,提前过滤掉不符合条件的记录,减少回表次数。
  • 不要建冗余/重复索引

6. 事务与隔离级别

ACID 回顾

  • Atomicity(原子性):通过 Undo Log 实现。
  • Consistency(一致性):由数据库约束 + 业务逻辑保证。
  • Isolation(隔离性):由锁 + MVCC 实现。
  • Durability(持久性):通过 Redo Log 实现。

四种隔离级别

隔离级别 脏读 不可重复读 幻读
READ UNCOMMITTED ✅ 可能 ✅ 可能 ✅ 可能
READ COMMITTED ✅ 可能 ✅ 可能
REPEATABLE READ(MySQL 默认) ❌(InnoDB 用间隙锁解决了)
SERIALIZABLE
  • READ COMMITTEDREPEATABLE READ 都是通过 MVCC 实现的快照读。
  • REPEATABLE READ 下,普通的 SELECT 不会加锁,而是读取快照版本;加锁读(SELECT ... FOR UPDATE)会使用间隙锁防止幻读。

7. MVCC(多版本并发控制)

MVCC 使 InnoDB 在加锁的情况下实现 非阻塞读

  • 核心思想:每行数据可能有多个版本(通过 Undo Log 串联)。
  • 每个事务启动时,会生成一个 Read View,包含当前活跃事务 ID 列表。
  • 可见性判断:根据版本的事务 ID 与 Read View 比较,决定该行是否对当前事务可见。
  • 不同隔离级别的 Read View 生成时机不同:
    • RC:每次查询都生成新的 Read View → 会出现不可重复读。
    • RR:只在事务第一次查询时生成 Read View → 保证重复读一致。

8. 锁机制

8.1 锁粒度

  • 表锁LOCK TABLES ... 或 MyISAM 默认锁。
  • 行锁:InnoDB 默认,通过索引实现,不是直接锁行,而是锁索引记录。
  • 间隙锁(Gap Lock):锁定一个范围(不包含记录本身),防止幻读。
  • 临键锁(Next-Key Lock):行锁 + 间隙锁,是 RR 级别下默认的锁。

8.2 锁类型

  • 共享锁(S)SELECT ... LOCK IN SHARE MODE
  • 排他锁(X)SELECT ... FOR UPDATEUPDATEDELETE
  • 意向锁:表级锁,表示事务想要在表中某行加 S 或 X 锁,用于快速判断表锁是否可行。

8.3 死锁

  • 两个或多个事务相互持有对方需要的锁。
  • InnoDB 会自动检测死锁,回滚代价较小的事务(可通过 innodb_deadlock_detect 控制)。

9. SQL 优化实战(常见思路)

9.1 慢查询定位

  • 开启慢查询日志:slow_query_log=1,设置 long_query_time
  • 使用 EXPLAIN 分析执行计划,关注:
    • type:从好到差依次是 system > const > eq_ref > ref > range > index > ALL
    • possible_keys / key:实际使用的索引。
    • rows:预估扫描行数。
    • ExtraUsing filesortUsing temporary 是优化重点。

9.2 索引失效场景

  • 对索引列使用函数、表达式(如 WHERE DATE(create_time) = '2025-01-01')。
  • 隐式类型转换(如 varchar 字段与 int 比较)。
  • LIKE 以 % 开头('%abc')。
  • OR 条件中,部分字段没有索引(除非覆盖所有 OR 字段)。

9.3 分页优化

  • 避免 LIMIT 1000000,10 → 会扫描前 100 万行再丢掉。
  • 改进方法:
    • 延迟关联:SELECT * FROM t JOIN (SELECT id FROM t ORDER BY id LIMIT 1000000,10) tmp ON t.id = tmp.id
    • 记住上一页最大 ID:WHERE id > last_id ORDER BY id LIMIT 10(适用于主键自增且无删除)。

9.4 写优化

  • 批量插入:INSERT INTO ... VALUES (1,2),(3,4)... 比单条快很多。
  • 适当调整 innodb_flush_log_at_trx_commit
    • 1(默认)------ 每次提交都刷盘,最安全。
    • 0 / 2 ------ 牺牲一点持久性,提升写入性能。

10. 常用运维与监控

  • SHOW ENGINE INNODB STATUS:查看 InnoDB 内部状态(锁、事务、缓冲池等)。
  • SHOW PROCESSLIST:查看当前连接与执行语句。
  • performance_schemasys 库:用于诊断锁等待、查询性能。
  • pt-query-digest:分析慢查询日志的工具。

写在最后

MySQL 的知识体系非常庞杂,但只要你理清 架构分层InnoDB 存储引擎索引日志事务与锁 这几条主线,剩下的细节都可以按图索骥。

如果能亲手在本地搭建一个 MySQL,结合 EXPLAINSHOW ENGINE 去观察 SQL 的行为,会比只看文章深刻得多。

如果你对某个点(比如 MVCC 底层、Redo Log 的组提交、Online DDL 原理等)想深入细节,也可以告诉我,我再单独展开。

希望这篇梳理对你有帮助。

相关推荐
minji...2 小时前
MySQL数据库 (四) MySQL的数据类型,tinyint,float,decimal,枚举enum和集合set
数据库·mysql·tinyint·enum·decimal·varchar·bit
todoitbo3 小时前
从 MySQL 到 KingbaseES:Database、Schema、User 一次讲透
数据库·mysql·国产数据库·kingbasees
千云3 小时前
100w大表0停机回滚:我们为什么放弃Undo Log,选择表名切换?
数据库·后端·mysql
AC赳赳老秦3 小时前
用 OpenClaw 制定技术学习计划:根据目标岗位自动生成学习路线、推荐学习资源
开发语言·c++·人工智能·python·mysql·php·openclaw
前进的李工4 小时前
MySQL性能优化:索引与子查询实战技巧
数据库·sql·mysql·性能优化
段ヤシ.4 小时前
回顾Java知识点,面试题汇总Day13:数据库MySQL(持续更新)
java·数据库·mysql
ULIi096kr5 小时前
MySQL磁盘爆满快速排查方案:一键查询库表空间、定位占用大户(RDS/自建通用)
数据库·mysql
Cx330❀5 小时前
【MySQL基础】库与表的全面操纵指南
linux·服务器·网络·数据库·c++·mysql
Database_Cool_5 小时前
AI 时代的数据仓库:阿里云 AnalyticDB MySQL 向量检索 + SQL 分析一体化实战
数据仓库·人工智能·mysql·阿里云