MySQL 架构全解

候选人小周在面试字节跳动的 MySQL 环节时,面试官翻开简历上"熟悉 MySQL 架构"这一行,开口问道:

"能画一下 MySQL 的整体架构图吗?Server 层和存储引擎层各自负责什么?"

小周开始在纸上画了起来,画到一半突然停住:"呃,Server 层有连接器、解析器、优化器...存储引擎层的话,用的是 InnoDB..."

面试官没说话,等着他继续。小周又补了一句:"然后...好像没了?"

面试官追问:"那执行器在哪?缓冲池呢?redo log 和 binlog 分别在哪一层?"

小周开始冒汗。

这道题,我见过太多候选人只能画个大概,却说不清楚每一层到底在干什么、它们之间怎么配合。MySQL 架构不是背出来的,是理解出来的。今天这篇,带你把 MySQL 从上到下全部过一遍。

一、MySQL 整体架构 🔴

1.1 两层架构概述

MySQL 分为两层:Server 层存储引擎层

┌─────────────────────────────────────────────────────────┐
│                      Server 层                          │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │
│  │ 连接器    │→│ 解析器    │→│ 优化器    │→│  执行器   │ │
│  └──────────┘ └──────────┘ └──────────┘ └───────────┘ │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐                │
│  │ 管理器    │ │ 缓存     │ │ 日志      │                │
│  └──────────┘ └──────────┘ └──────────┘                │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│                   存储引擎层(可插拔)                    │
│  ┌───────────┐ ┌───────────┐ ┌───────────┐              │
│  │ InnoDB    │ │ MyISAM   │ │ Memory    │  ...         │
│  │ (默认)     │ │           │ │           │              │
│  └───────────┘ └───────────┘ └───────────┘              │
│  ┌─────────────────────────────────────────────────┐   │
│  │              底层存储结构                          │   │
│  │  缓冲池  |  redo log  |  undo log  |  数据页      │   │
│  └─────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘

Server 层负责 SQL 层面的通用功能,包括连接管理、权限校验、SQL 解析、查询优化、结果返回等。存储引擎层负责数据真正的存取方式,不同引擎有不同的存储结构、索引机制和事务支持。

1.2 ❌ 错误示范

候选人原话:"MySQL 架构就是客户端连上去,然后执行 SQL,返回结果。"

问题诊断

  • 把 MySQL 当成了一个黑盒子,只知道输入输出,不知道中间过程
  • 混淆了"连接层"和"Server 层",不清楚有多少组件在参与一条 SQL 的执行
  • 不知道存储引擎是可插拔的,不理解 InnoDB 和 MyISAM 的本质区别
  • 完全不了解 redo log 和 binlog 的分工

面试官内心 OS:这个候选人肯定没有系统性学过 MySQL 原理,估计只会写 SQL,连 mysqld 进程是怎么工作的都不清楚。

1.3 标准回答

P5 级别:能说清楚两层架构

MySQL 整体分为 Server 层和存储引擎层。Server 层负责 SQL 的解析、优化和执行,包括连接器、解析器、优化器和执行器四大组件。存储引擎层负责数据的物理存储,MySQL 支持多种引擎,最常用的是 InnoDB,它是 MySQL 5.5 之后的默认引擎,支持事务和行级锁。

P6 级别:能说清各组件职责和数据流向

Server 层核心组件

组件职责关键点
连接器管理客户端连接、权限校验TCP 三次握手后验证用户名密码,支持长连接和连接池
查询缓存缓存 SELECT 结果(MySQL 8.0 已移除)命中则直接返回,但维护成本高,8.0 后被废弃
解析器词法分析 + 语法分析,生成解析树将 SQL 字符串转化为 AST
优化器生成执行计划,选择索引/JOIN 顺序代价模型评估,不执行 SQL,只生成计划
执行器调用存储引擎接口,按计划执行打开表时检查权限,操作前调用引擎读取接口

存储引擎层核心组件(以 InnoDB 为例):

组件职责位置
缓冲池(Buffer Pool)缓存数据页和索引页,减少磁盘 IO内存中,默认 128MB
redo log buffer记录修改操作,保证持久性内存中
系统表空间存储数据字典、双写缓冲ibdata1 文件
用户表空间(.ibd)存储表数据和索引每个表一个 .ibd 文件
undo log存储 MVCC 的历史版本系统表空间或 undo 表空间

一条 UPDATE 语句的数据流向:

客户端 → 连接器(认证)→ 解析器(生成 AST)→ 优化器(选索引)→ 执行器
       → 调用 InnoDB 引擎接口
       → 缓冲池中修改数据页(标记为脏页)
       → 写入 redo log buffer
       → 事务提交时刷 redo log 到磁盘
       → 异步刷脏页到磁盘
       → 返回执行结果

P7 级别:能说清 binlog 和 redo log 的区别与配合

binlog 属于 Server 层,redo log 属于 InnoDB 引擎层。这是两个最容易混淆的点。

日志所属层级记录内容用途
binlogServer 层所有修改操作(逻辑日志)主从复制、数据恢复
redo logInnoDB 层物理页修改(物理日志)crash-safe、崩溃恢复
undo logInnoDB 层行记录的历史版本MVCC、回滚事务

两阶段提交保证了崩溃恢复时的一致性:

  1. 写入 redo log(prepare 状态)
  2. 写入 binlog
  3. 提交事务(commit 状态)

如果 crash 发生在第 1 步和第 2 步之间,恢复时 redo log 未 commit,回滚;如果 redo log prepare 成功但 binlog 失败,同样回滚。

【面试官心理】 我问他 MySQL 架构,其实是在试探他有没有系统性地看过 MySQL 源码或相关书籍。能说出 binlog 和 redo log 的区别是 P6 的及格线,能说清两阶段提交的是加分项。如果他还能说出"为什么 binlog 不在引擎层"这样的追问,说明他对 MySQL 的分层设计有真正思考。

1.4 追问升级

追问 1:MySQL 8.0 为什么移除了查询缓存?

答:查询缓存的问题在于,任何对表的 DML 操作都会导致该表的所有缓存失效。在高并发写入场景下,缓存命中率极低,维护缓存的开销反而成了瓶颈。因此 MySQL 8.0 直接移除了查询缓存。

追问 2:执行器打开表的时候检查的是什么权限?

答:检查的是用户对该表的 SELECT/INSERT/UPDATE/DELETE 权限。执行器在每次调用存储引擎读取之前,都会验证权限。

追问 3:如果一条 SQL 没有命中索引,执行器是怎么工作的?

答:执行器调用存储引擎的全表扫描接口,存储引擎一条一条地读取数据页,调用执行器的读取回调,逐行判断条件,返回给客户端。

二、存储引擎对比 🟡

2.1 InnoDB vs MyISAM

面试官接着问:"既然 MySQL 支持多种存储引擎,那你主要用过哪些?InnoDB 和 MyISAM 的区别是什么?"

小周说:"InnoDB 支持事务,MyISAM 不支持。"

面试官追问:"还有呢?"

小周:"InnoDB 支持行级锁,MyISAM 只支持表级锁...还有...InnoDB 的索引是聚簇索引,MyISAM 是非聚簇..."

面试官点点头:"那它们的数据文件结构有什么区别?"

小周:"...好像不一样?"

这道题,P6 候选人必须能完整答出以下对比:

特性InnoDBMyISAM
事务支持✅ 支持 ACID❌ 不支持
锁粒度行级锁 + 间隙锁表级锁
聚簇索引✅ 叶子节点存完整数据❌ 非聚簇,叶子节点存指针
崩溃恢复✅ crash-safe(redo log)❌ 需手动修复
外键✅ 支持❌ 不支持
并发性能高(行锁 + MVCC)低(表锁)
count(*)全表扫描,较慢保存了计数器,快
数据文件.ibd(表空间).MYD + .MYI + .frm
全文索引✅ 支持(5.6+)✅ 原生支持
适用场景OLTP、高并发、事务场景OLAP、只读场景、历史表

【面试官心理】 这道题考的是候选人对 MySQL 引擎选型的理解。能背出表格的人很多,但真正理解"为什么 InnoDB 是默认引擎"的人不多。我追问数据文件结构,是想看他有没有动手看过 MySQL 的物理存储。

2.2 引擎选型建议

💡

生产环境 99% 的场景用 InnoDB。除非你有非常明确的理由(比如确实只需要简单的 SELECT 查询,且数据量极大),否则不要用 MyISAM。

⚠️

MyISAM 的 count(*) 虽然快,但它是表级锁,并发写入时会阻塞整个表。不要因为 count 快就选择 MyISAM。

三、生产避坑

3.1 缓冲池配置不当

场景:订单表数据量 5000 万条,每次查询要 3 秒。监控显示磁盘 IO 频繁,CPU 使用率不高。

根因:MySQL 缓冲池默认 128MB,对 5000 万条订单来说完全不够用。大部分查询都要从磁盘读取数据页,磁盘 IO 成为瓶颈。

排查方法

-- 查看缓冲池大小
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';

-- 查看缓冲池使用率
SHOW STATUS LIKE 'Innodb_buffer_pool%';

-- 监控命中率
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
-- Innodb_buffer_pool_read_requests: 总读请求
-- Innodb_buffer_pool_reads: 从磁盘读取次数
-- 命中率 = 1 - reads/requests

解决方案:将缓冲池设为服务器可用内存的 60%~80%,并启用多个缓冲池实例减少争用:

SET GLOBAL innodb_buffer_pool_size = 12884901888;  -- 12GB
SET GLOBAL innodb_buffer_pool_instances = 8;         -- 8 个实例

3.2 redo log 配置不当

场景:高并发写入时,MySQL 写入性能突然下降,IO util 飙到 100%。

根因:redo log 文件太小(默认 48MB x 2),在高并发写入场景下,redo log 频繁切换,导致频繁的刷盘操作。

解决方案

-- 查看 redo log 配置
SHOW VARIABLES LIKE 'innodb_log%';

-- 调整 redo log 大小(需要重启)
-- innodb_log_file_size = 1GB
-- innodb_log_files_in_group = 3

redo log 太小的表现是 Innodb_log_waits 计数器持续增长。

3.3 线上架构分层建议

组件职责配置建议
连接层连接池、负载均衡推荐使用 Druid/HikariCP,连接数合理设置
Server 层SQL 解析优化无需过多配置,重点在 SQL 质量
引擎层数据存储InnoDB 默认,缓冲池大小根据内存规划
OS 层文件系统、磁盘推荐 XFS,SSD/NVMe 盘,RAID 配置

四、工程选型

4.1 什么场景可以用 MyISAM?

  1. 纯读场景:报表系统、只读的历史数据查询,不需要事务,不需要并发写入
  2. 空间型数据:MyISAM 对空间函数支持较好,GIS 场景可选
  3. 极致的 count 性能:读多写少且对 count 查询有极致要求的场景(但代价是放弃并发写入)

4.2 为什么 InnoDB 成了默认引擎?

  • 互联网业务的特点是高并发写入,MyISAM 的表级锁是致命缺陷
  • 事务是业务一致性的基础,没有事务就无法保证数据完整性
  • crash-safe 保证服务器宕机后数据不丢失
  • MVCC 提供了高效的并发读写能力

【面试官心理】 我在面试中问架构问题,最终是想确认候选人有没有"根据业务场景选择合适技术方案"的意识。如果他无脑选 InnoDB,不说为什么,说明他只是跟着默认配置走,没有独立思考。


级别考察重点期望回答
P5基本架构能画出两层架构,说出连接器、解析器、优化器、执行器
P6组件分工 + 引擎对比能说清数据流向、InnoDB vs MyISAM 区别、缓冲池作用
P7深度理解 + 方案选型能说清 binlog vs redo log、两阶段提交、生产调优经验