mysql结构的一些整理
MySQL 整体逻辑架构图
┌───────────────────────────────────────────────────────────────────────┐
│ 1. 连接层 (Client Connectors) │
│ [ JDBC / ODBC / Net / PHP / Python / Go / CLI / Navicat... ] │
└───────────────────────────────────┬───────────────────────────────────┘
│ (TCP/IP / 线程池连接)
▼
┌───────────────────────────────────────────────────────────────────────┐
│ 2. 服务层 (Server 层) │
│ │
│ ┌───────────────────────┐ ┌─────────────────────────────────────┐ │
│ │ 连接管理器 & 权限验证 │ │ 查询缓存 (Query Cache) │ │
│ │ (Connection/Auth Manager)│ │ (MySQL 8.0 已完全移除,老版本有) │ │
│ └───────────┬───────────┘ └──────────────────┬──────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 解析器 (Parser) & 预处理器 (Preprocessor) │ │
│ │ - 词法分析、语法分析、生成解析树 (AST) │ │
│ └───────────────────────────────┬─────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 优化器 (Optimizer) │ │
│ │ - 选择索引、决定表关联顺序、生成执行计划 (Execution Plan) │ │
│ └───────────────────────────────┬─────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 执行器 (Executor) │ │
│ │ - 权限检查、调用存储引擎 API 读写数据 │ │
│ └───────────────────────────────┬─────────────────────────────────┘ │
└───────────────────────────────────│───────────────────────────────────┘
│ (通过统一的存储引擎 API 交互)
▼
┌───────────────────────────────────────────────────────────────────────┐
│ 3. 存储引擎层 (Pluggable Storage Engines) │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───┐ │
│ │ InnoDB │ │ MyISAM │ │ Memory │ │...│ │
│ │(事务、行锁、MVCC)│ │ (表锁、不支持) │ │ (内存表、极快) │ │ │ │
│ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘ └───┘ │
└───────────│───────────────────│───────────────────│───────────────────┘
▼ ▼ ▼
┌───────────────────────────────────────────────────────────────────────┐
│ 4. 系统文件层 (File System / Disk) │
│ │
│ [ 数据文件 (.ibd / .MYD) ] [ 结构文件 (.frm / MyData) ] │
│ [ 日志文件 (Redo / Undo / Binlog / Error Log / Slow Log) ] │
└───────────────────────────────────────────────────────────────────────┘
数据页的流动逻辑
【服务层/执行器】
│
▼ (想要读取或修改某行数据)
┌────────────────────────────────────────┐
│ 【InnoDB 引擎层 - 内存 Buffer Pool】 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───┐ │
│ │ 数据页 A │ │ 数据页 B │ │...│ │ (内存中的数据页,完全映射磁盘结构)
│ └──────────┘ └──────────┘ └───┘ │
└────────────────────▲───────────────────┘
│ (若内存中没有,则产生 I/O 读入内存)
▼
┌────────────────────────────────────────┐
│ 【系统文件层 - 磁盘 .ibd 文件】 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───┐ │
│ │ 数据页 A │ │ 数据页 B │ │...│ │ (磁盘上连续的 16KB 物理块)
│ └──────────┘ └──────────┘ └───┘ │
└────────────────────────────────────────┘
磁盘文件全景结构图
/var/lib/mysql/ (MySQL Data 根目录)
├── ibdata1 <-- 系统表空间 (存储系统元数据、Change Buffer等)
├── undo_001 <-- 回滚日志文件 (Undo Log)
├── undo_002
├── #innodb_redo/ <-- 重做日志文件夹 (Redo Log)
│ ├── @ib_redo0
│ └── @ib_redo1
├── ib_buffer_pool <-- 缓冲池状态文件 (重启时快速恢复内存缓存)
│
├── oms/ <-- 【数据库 oms 对应的文件夹】
│ ├── orders.ibd <-- 【表 orders】(包含表结构 + 16KB 数据页 + 索引页)
│ └── users.ibd <-- 【表 users】(包含表结构 + 16KB 数据页 + 索引页)
│
└── sys/ <-- 系统自带的 sys 数据库文件夹
└── ...
索引
聚簇索引(Clustered Index)的存储:它就是表本身
在 InnoDB 中,一张表的数据行在磁盘上不是杂乱无章排放的,而是必须按照主键的顺序,组织成一棵 B+ 树。叶子节点(Leaf Nodes): 存放的是真正的、完整的整行数据(包含你定义的 order_no, price, create_time 等所有字段)。非叶子节点(Non-Leaf Nodes): 只存放“主键 ID + 下一层数据页的指针”。文件层表现: 我们之前提到的那些 16KB 的数据页,有些变成了这棵树的枝干(非叶子节点页),有些变成了这棵树的树叶(叶子节点页)。它们都统统存在 表名.ibd 文件里。
二级索引(Secondary Index)的存储:它是另一棵 B+ 树
如果你给表里的 order_no(订单号)字段加了一个普通索引,MySQL 会怎么存?独立成树: MySQL 会在同一个 表名.ibd 文件里,额外再划出一批 16KB 的数据页,为 order_no 单独构建一棵全新的 B+ 树。叶子节点: 这棵二级索引树的叶子节点里,不包含整行数据的全部字段。它只存放两样东西:当前索引列的值 (order_no) + 对应的主键 ID。文件层表现: 这棵新树的数据页和主键树的数据页混交在同一个 .ibd 文件里,通过页头(Page Header)里的标记来区分自己属于哪一个索引。
索引在 .ibd 文件内部的物理全景图
【表名.ibd 文件 (总大小: N 个 16KB 页面)】
┌────────────────────────────────────────────────────────────────────────┐
│ [文件头/表结构元数据 SDI] (MySQL 8.0 特有,占前几个页) │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ 【主键 B+ 树 区域 (聚簇索引)】 │
│ ├── [ 16KB 索引页 ] ───> [ 16KB 索引页 ] (非叶子节点:只存 ID + 指针) │
│ └── [ 16KB 数据页 ] ───> [ 16KB 数据页 ] (叶子节点:存【完整整行数据】) │
│ │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ 【order_no 索引 B+ 树 区域 (二级索引)】 │
│ ├── [ 16KB 索引页 ] ───> [ 16KB 索引页 ] (非叶子节点:只存单列+指针) │
│ └── [ 16KB 数据页 ] ───> [ 16KB 数据页 ] (叶子节点:只存【order_no+主键ID】)
│ │
└────────────────────────────────────────────────────────────────────────┘
索引是如何在文件层协同工作的?(回表查询)
当你执行:SELECT * FROM orders WHERE order_no = ‘ABC’;执行器调用接口,InnoDB 打开 orders.ibd 文件。引擎先去 order_no 二级索引树 的物理页面里疯狂二分查找,在叶子节点找到了 ‘ABC’,并拿到了它绑定的小尾巴——主键 id = 99。因为你要的是 SELECT *(所有字段),二级索引树里没有其他字段,这就触发了 “回表”。引擎拿着 id = 99,转头去同一个文件内的 主键 B+ 树 的物理页面里再次查找,在叶子节点顺利捞出 id=99 的完整整行数据,返回给用户。
- 点赞
- 收藏
- 关注作者
评论(0)