Skip to content

MySQL 架构分层

问“MySQL 有几层”,面试和学习里通常有两种回答方式:

  1. 简化三层架构:连接层、Server 层、存储引擎层。
  2. 展开五层架构:客户端层、连接层、SQL 层、存储引擎层、文件与日志层。

更推荐这样记:

MySQL 对外看是三层:连接层负责连接和权限,Server 层负责 SQL 解析、优化和执行调度,存储引擎层负责真正的数据读写。再往下展开,InnoDB 会依赖 Buffer Pool、数据页、redo log、undo log、binlog 协调等机制保证性能、事务和恢复。

学习目标

目标需要掌握什么
知道分层能说清连接层、Server 层、存储引擎层分别做什么
知道边界知道 binlog 属于 Server 层,redo/undo 属于 InnoDB
知道流程能讲清一条 select、update 从客户端到 InnoDB 的链路
知道为什么知道为什么 MySQL 要把 SQL 层和存储引擎层分开
会排查慢 SQL、连接满、锁等待、磁盘慢分别可能在哪一层
会面试能用清晰分层回答“MySQL 架构”“SQL 执行流程”

简化三层架构

最常见的学习模型是三层:

mermaid
flowchart TD
    A["连接层<br/>连接、认证、权限、线程"] --> B["Server 层<br/>解析、预处理、优化、执行"]
    B --> C["存储引擎层<br/>InnoDB、MyISAM、Memory"]
    C --> D["磁盘文件和日志<br/>数据页、索引页、redo、undo"]
负责什么常见组件
连接层建立连接、认证账号、权限校验、连接管理连接器、线程、权限表
Server 层处理 SQL 语义,生成执行计划,调用引擎接口解析器、预处理器、优化器、执行器、binlog
存储引擎层真正读写数据、维护索引、处理事务和锁InnoDB、Buffer Pool、B+Tree、redo、undo

为什么这样分层:Server 层不用关心数据到底存在 InnoDB 还是 MyISAM;存储引擎层也不用关心 SQL 文本怎么解析。这样 MySQL 可以支持多个存储引擎。

展开五层架构

如果面试官追问“再细一点”,可以展开成五层:

mermaid
flowchart TD
    A["客户端层<br/>JDBC、Navicat、MyBatis"] --> B["连接层<br/>TCP、认证、权限、连接池"]
    B --> C["SQL 层<br/>解析、预处理、优化、执行"]
    C --> D["存储引擎层<br/>InnoDB 引擎接口"]
    D --> E["文件与日志层<br/>表空间、数据页、redo、undo"]
层级说明重点
客户端层发起 SQL 请求JDBC、连接池、ORM、命令行客户端
连接层管理连接和权限连接数、认证、权限、空闲超时
SQL 层理解并执行 SQL解析器、优化器、执行器、binlog
存储引擎层访问数据和索引InnoDB、锁、MVCC、Buffer Pool
文件与日志层数据落盘和恢复表空间、数据页、redo log、undo log

这五层不是官方唯一叫法,但非常适合学习和面试表达。

第一层:客户端层

客户端层不是 MySQL Server 内部的一部分,但它决定 SQL 怎么发到 MySQL。

常见客户端:

客户端示例
Java 程序JDBC、MyBatis、JPA、HikariCP
管理工具Navicat、DataGrip、MySQL Workbench
命令行mysql -h127.0.0.1 -uroot -p
中间件ShardingSphere、MyCat、ProxySQL

常见问题:

现象可能原因
应用连接数据库慢连接池配置小、网络慢、数据库连接数满
偶发 timeoutSQL 慢、连接池等待、网络抖动
大量短连接没用连接池或连接池配置错误
事务没提交ORM 或代码没有正确管理事务

所以排查 MySQL 问题时,不要只看数据库,也要看应用连接池、超时配置和 ORM 生成的 SQL。

第二层:连接层

连接层负责处理客户端连接。

mermaid
flowchart TD
    A["客户端发起 TCP 连接"] --> B["MySQL 接收连接"]
    B --> C["账号密码认证"]
    C --> D["权限加载和校验"]
    D --> E["分配连接线程或线程资源"]
    E --> F["等待客户端发送 SQL"]

连接层主要做:

能力说明
连接建立基于 TCP 建立客户端和 MySQL Server 的连接
用户认证校验用户名、密码、主机来源
权限校验判断是否有库、表、列、操作权限
连接管理维护连接状态、空闲时间、当前数据库、事务状态
线程处理每个连接对应服务线程或线程池资源

常见参数:

参数作用
max_connections最大连接数
wait_timeout非交互连接空闲超时时间
interactive_timeout交互连接空闲超时时间
max_user_connections单用户最大连接数

查看连接:

sql
show processlist;
show global status like 'Threads%';
show variables like 'max_connections';

如果 Threads_connected 很高,应用可能连接泄漏、连接池过大,或者 SQL 慢导致连接释放不及时。

第三层:SQL 层,也叫 Server 层

Server 层是 MySQL 的通用 SQL 处理层。大多数 EXPLAIN、优化器、binlog 都属于这一层。

mermaid
flowchart TD
    A["SQL 文本"] --> B["解析器"]
    B --> C["预处理器"]
    C --> D["优化器"]
    D --> E["执行器"]
    E --> F["调用存储引擎接口"]

解析器

解析器负责把 SQL 文本变成 MySQL 能理解的结构。

它做两件事:

步骤说明
词法分析把字符串拆成关键字、表名、列名、常量、操作符
语法分析判断 SQL 是否符合 MySQL 语法

例如:

sql
select id, username from users where id = 1;

解析器会识别出:

text
select 列表:id, username
from 表:users
where 条件:id = 1

如果 SQL 写错,比如:

sql
select from users;

错误通常发生在解析器阶段。

预处理器

预处理器负责进一步检查语义:

检查示例
表是否存在users 表是否存在
字段是否存在username 字段是否存在
字段是否有歧义多表都有 id 时是否明确指定
权限是否满足当前用户是否能查这张表

语法正确不代表语义正确。比如字段不存在,语法层面可能能解析,但预处理阶段会报错。

优化器

优化器负责决定“怎么执行更便宜”。

它会考虑:

优化点说明
选择哪个索引idx_user_id 还是 idx_status_time
表连接顺序多表 join 谁先访问
访问方式const、ref、range、ALL
是否走覆盖索引查询字段是否都在索引里
是否需要排序能否利用索引顺序
估算扫描行数根据统计信息估算 rows

优化器依赖统计信息,所以它可能选错索引。详细看 EXPLAIN 执行计划

执行器

执行器负责按优化器选出的计划真正执行。

它会:

  1. 检查执行权限。
  2. 打开表。
  3. 调用存储引擎接口读取第一行。
  4. 判断 WHERE 条件是否满足。
  5. 满足就返回给客户端。
  6. 继续调用引擎读取下一行,直到结束。

执行器本身不直接理解 InnoDB 页结构,它通过统一的存储引擎接口和 InnoDB 交互。

binlog 属于 Server 层

binlog 是 MySQL Server 层的日志,不属于 InnoDB。

日志所属层作用
binlogServer 层主从复制、增量恢复、审计回放
redo logInnoDB 层崩溃恢复,保证已提交事务不丢
undo logInnoDB 层回滚和 MVCC 旧版本

这也是为什么 redo log 和 binlog 要通过两阶段提交保证一致。详细看 redo log 与 binlog

第四层:存储引擎层

存储引擎层负责真正的数据读写。MySQL 支持多种存储引擎,但商业项目里最常用的是 InnoDB。

查看支持的引擎:

sql
show engines;

常见引擎:

引擎特点是否常用
InnoDB支持事务、行锁、MVCC、崩溃恢复最常用
MyISAM不支持事务,表锁为主老系统可能有
Memory数据在内存,重启丢失特殊临时场景

InnoDB 主要负责:

能力说明
B+Tree 索引聚簇索引、二级索引、范围扫描
Buffer Pool缓存数据页和索引页
行锁锁索引记录,不是简单锁物理行
MVCC通过 undo log 和 Read View 支持快照读
redo log崩溃恢复
undo log回滚和历史版本
change buffer优化部分二级索引写入
purge清理不再需要的历史版本

第五层:文件与日志层

InnoDB 最终要把数据和日志落到磁盘。

mermaid
flowchart TD
    A["InnoDB 内存结构"] --> B["Buffer Pool"]
    A --> C["Log Buffer"]
    B --> D["数据文件和索引页"]
    C --> E["redo log 文件"]
    A --> F["undo 表空间或回滚段"]

常见文件和日志:

内容说明
表空间文件保存 InnoDB 表和索引数据
数据页InnoDB 默认以 16KB 页为基本读写单位
redo log记录页修改,用于崩溃恢复
undo log保存旧版本,用于回滚和 MVCC
binlogServer 层日志,用于复制和恢复
relay log从库接收主库 binlog 后保存的中继日志
slow log慢 SQL 日志,用于性能排查

很多性能问题都和这一层有关:

问题可能原因
磁盘 IO 高Buffer Pool 命中率低、大量随机读、刷脏页
提交慢redo flush、binlog sync、磁盘 fsync 慢
undo 膨胀长事务导致历史版本无法清理
主从延迟binlog 产生快,从库回放慢

SELECT 查询经过几层

mermaid
flowchart TD
    A["客户端发送 SELECT"] --> B["连接层校验连接和权限"]
    B --> C["解析器解析 SQL"]
    C --> D["预处理器检查表和列"]
    D --> E["优化器选择索引和执行计划"]
    E --> F["执行器调用 InnoDB"]
    F --> G["InnoDB 查 B+Tree"]
    G --> H{"Buffer Pool 是否有页"}
    H -- "有" --> I["直接读内存页"]
    H -- "没有" --> J["从磁盘读页到 Buffer Pool"]
    I --> K["返回行给执行器"]
    J --> K
    K --> L["执行器过滤、排序、返回客户端"]

关键理解:

  1. SQL 语法处理在 Server 层。
  2. 索引页、数据页读取在 InnoDB 层。
  3. 是否走索引由优化器决定。
  4. 真正读取页的是存储引擎。
  5. 返回结果前可能还要在 Server 层过滤、排序、分组。

UPDATE 更新经过几层

mermaid
flowchart TD
    A["客户端发送 UPDATE"] --> B["连接层校验"]
    B --> C["Server 层解析和优化"]
    C --> D["执行器调用 InnoDB 定位记录"]
    D --> E["InnoDB 加锁"]
    E --> F["写 undo log 旧版本"]
    F --> G["修改 Buffer Pool 中的数据页"]
    G --> H["写 redo log prepare"]
    H --> I["Server 层写 binlog"]
    I --> J["redo log commit"]
    J --> K["事务提交成功"]

这个流程能解释几个高频问题:

问题解释
为什么更新要加锁防止并发写同一记录导致数据错乱
为什么能回滚undo log 保存了修改前版本
为什么提交后宕机能恢复redo log 能重放已提交页修改
为什么主从复制靠 binlogbinlog 是 Server 层逻辑变更日志
为什么 redo 和 binlog 要两阶段提交保证 InnoDB 恢复和主从复制看到同一事务结果

MySQL 8 查询缓存去哪了

老版本 MySQL 有 Query Cache,位于 Server 层。它会缓存完整 SQL 的查询结果。

但 MySQL 8 已经移除查询缓存。原因是:

  1. SQL 必须完全相同才容易命中。
  2. 表更新会导致相关缓存失效。
  3. 高并发下维护 Query Cache 会带来锁竞争。
  4. 商业项目更常用 Redis、本地缓存或应用层缓存。

所以现在学习 MySQL 架构时,不要再把 Query Cache 当作核心能力。

分层和排查怎么对应

现象优先看哪层排查方向
连接数满连接层show processlist、连接池、max_connections
SQL 语法报错SQL 层解析器SQL 拼写、关键字、括号
字段不存在SQL 层预处理器表结构、别名、字段名
有索引但不用SQL 层优化器统计信息、选择性、EXPLAIN
查询扫描很多行优化器 + InnoDB索引设计、rows、回表
锁等待InnoDB行锁、间隙锁、事务未提交
普通查询读到旧版本InnoDB MVCCRead View、隔离级别
提交慢日志层redo flush、binlog sync、磁盘 IO
主从延迟Server 日志层 + 从库执行binlog、relay log、回放线程
宕机恢复慢InnoDB 日志层redo checkpoint、脏页、事务量

商业场景:为什么慢 SQL 不能只看 SQL

假设订单列表查询慢:

sql
select id, order_no, status, created_at
from orders
where user_id = 1001
  and status = 1
order by created_at desc
limit 20;

按分层分析:

可能问题
客户端层连接池等待,接口线程被占满
连接层数据库连接数接近上限
SQL 层优化器没选到合适索引
存储引擎层索引不匹配,扫描大量页或大量回表
文件日志层磁盘 IO 高,Buffer Pool 命中率低

这就是为什么排查慢 SQL 要结合:

  1. 应用耗时。
  2. 连接池等待。
  3. EXPLAIN
  4. 慢日志。
  5. Buffer Pool 命中率。
  6. 磁盘 IO。

常见误区

误区正确理解
MySQL 只有一层,就是数据库MySQL 至少要区分连接层、Server 层、存储引擎层
优化器属于 InnoDB优化器属于 Server 层
binlog 属于 InnoDBbinlog 属于 Server 层
redo log 和 binlog 一样redo 是 InnoDB 崩溃恢复日志,binlog 是 Server 复制恢复日志
SQL 执行就是直接读磁盘大量读取先走 Buffer Pool,缺页才读磁盘
InnoDB 行锁锁的是物理行InnoDB 行锁加在索引记录上
Query Cache 还能优化 MySQL 8MySQL 8 已经移除 Query Cache

面试回答模板

如果被问“MySQL 有几层”,可以这样答:

text
MySQL 通常可以按三层理解:连接层、Server 层和存储引擎层。连接层负责客户端连接、认证、权限和连接管理;Server 层负责 SQL 解析、预处理、优化器生成执行计划、执行器调用存储引擎,同时 binlog 也在 Server 层;存储引擎层负责真正的数据读写,最常用的是 InnoDB,它负责 B+Tree 索引、Buffer Pool、事务、锁、MVCC、redo log 和 undo log。再往下是文件和日志层,保存表空间、数据页、redo、undo 等。执行 select 时,SQL 先经过连接、解析、优化,再由执行器调用 InnoDB 查索引和数据页;执行 update 时还会涉及加锁、undo、redo、binlog 和两阶段提交。

关联知识点

知识点继续学习什么
MySQL 总览MySQL 学习路线
InnoDB 存储结构页、行、B+Tree、Buffer Pool
索引知识点聚簇索引、二级索引、覆盖索引
EXPLAIN优化器和执行计划
事务ACID、隔离级别
锁机制行锁、间隙锁、临键锁
MVCCRead View、undo 版本链
redo log 与 binlogServer 层和 InnoDB 层日志协同

本章小结

MySQL 可以简化理解为三层:连接层、Server 层、存储引擎层;也可以展开为客户端层、连接层、SQL 层、存储引擎层、文件与日志层。连接层解决“谁连进来、有没有权限”,Server 层解决“SQL 怎么解析、怎么优化、怎么执行”,InnoDB 解决“数据怎么存、怎么查、怎么加锁、怎么恢复”。理解分层后,才能把慢 SQL、锁等待、连接满、主从延迟、崩溃恢复这些问题放到正确位置分析。