MySQL 中一条 SQL 语句的执行流程
在 MySQL 中,一条 SQL 语句的执行并非 “即时完成”,而是经过连接器、查询缓存、分析器、优化器、执行器等多个模块的协同处理,最终与存储引擎交互获取数据。
MySQL 架构概述
MySQL 内部分为服务层和引擎层。服务层负责 SQL 的解析、优化和执行协调,引擎层负责数据的实际存储与读取,采用插件式结构,支持多种引擎类型(如 InnoDB、MyISAM 等),其中 InnoDB 是 MySQL 的默认存储引擎,具备事务支持、行级锁和外键约束,适用于高并发、数据一致性要求高的场景。
服务层核心组件
连接器
负责客户端与 MySQL 的连接管理,包括身份验证、权限校验和连接维护。验证成功后,MySQL 会为每个客户端连接分配独立线程。
查询缓存
缓存 SQL 查询的结果,命中时直接返回以减少重复计算。但由于数据库数据变化频繁,缓存命中率低,逻辑上浪费性能,MySQL 5.7 版本默认不开启,8.0 版本完全弃用。
分析器
校验 SQL 语法正确性,拆解 SQL 结构,将 SQL 字符串解析为抽象语法树(AST),同时检查涉及的表、字段是否存在及用户是否有权限访问。
优化器
为 SQL 选择成本最低的执行计划,决定索引使用、表连接顺序等执行策略,生成物理执行计划。
执行器
根据优化器生成的执行计划,调用存储引擎接口执行数据操作。
查询语句的执行流程
连接建立与权限验证(连接器)
客户端通过连接器与 MySQL 建立连接,完成身份验证和权限校验,获取连接线程。
SQL 解析与校验(分析器)
分析器对 SQL 进行语法校验,拆解语句结构,生成抽象语法树,检查涉及的表、字段是否存在及用户权限。
执行计划优化(优化器)
优化器基于成本模型选择最佳执行计划,如确定使用的索引、表连接顺序等,生成物理执行计划。
执行计划执行(执行器)
执行器调用存储引擎接口,根据执行计划获取数据。
引擎层数据读取(InnoDB)
- 缓冲池检查:InnoDB 判断数据所在页是否在内存缓冲池中,若不在则从磁盘读入缓冲池。
- 数据处理:通过索引查找、数据遍历过滤等操作获取满足条件的数据行,涉及多版本并发控制(MVCC)、临时表排序等逻辑。
- 结果集组织:将符合条件的数据行组织成结果集,传递给服务层执行器。
结果集处理与返回(服务层)
执行器对引擎层返回的结果集进行筛选、组合、排序、分组聚合等处理,格式化后再次校验权限,最终返回给客户端。
增删改语句执行流程
增删改语句在服务层的执行步骤(连接、解析、优化、执行)与查询语句基本一致,但在引擎层(以 InnoDB 为例)存在显著差异,核心涉及事务处理和日志机制
事务开启与日志准备(InnoDB)
- 开启事务并获取事务 ID。
- 生成反向语句(用于回滚),写入 undo log,更新数据行的回滚指针和事务 ID。
数据页处理
- 缓冲池检查:若目标数据页不在缓冲池,通过唯一索引定位的数据会加载到缓冲池;非唯一索引定位的更新操作记录到 change buffer(延迟更新磁盘,空闲时异步刷新)。
- 内存更新:直接更新缓冲池中的数据,期间判断数据冲突(如锁竞争)。
事务提交(两阶段提交)
- prepare 阶段:写入 redo log,标记状态为 “prepare”。
- binlog 写入:Server 层触发 binlog 模块,将操作逻辑写入 binlog cache 并刷盘。
- commit 阶段:InnoDB 收到 binlog 写入确认后,将 redo log 刷盘并标记状态为 “commit”,事务正式提交。
脏页刷新与结果返回
- 缓冲池中被修改的脏页不会立即写入磁盘,由后台线程在空闲时异步刷新;即使未刷盘,因 redo log 已持久化,数据库崩溃后可通过 redo log 恢复。
- 执行器整理结果后返回给客户端。
关键机制说明
- undo log:用于事务回滚,记录数据修改前的状态。
- redo log:确保事务持久性,记录数据修改后的状态,崩溃后可恢复未刷盘的脏页。
- change buffer:优化非唯一索引更新性能,延迟磁盘写入,提升并发效率。
- 两阶段提交:保证 redo log 与 binlog 的数据一致性,避免单点日志故障导致的数据丢失或不一致。