一、前言
- 本文详细介绍了 MySQL 执行一条
SELECT
查询语句的内部流程。 - 通过理解这些流程,可以更好地了解 MySQL 的架构和工作原理。
二、MySQL 执行流程概览
MySQL 的架构分为两层:
-
Server 层:负责建立连接、分析和执行 SQL。
- 包括连接器、查询缓存、解析器、预处理器、优化器、执行器等模块。
- 实现了所有内置函数和跨存储引擎的功能(如存储过程、触发器、视图等)。
-
存储引擎层:负责数据的存储和提取。
- 支持多种存储引擎(如 InnoDB、MyISAM、Memory 等)。
- 不同存储引擎支持的索引类型不同,例如 InnoDB 使用 B+ 树索引。
三、执行 SELECT
语句的详细步骤
第一步:连接器
-
建立连接:
-
客户端通过 TCP 三次握手连接到 MySQL 服务。
-
使用命令
mysql -h[ip] -u[user] -p
连接到 MySQL 服务。# -h 指定 MySQL 服务的 IP 地址(本地可省略) # -u 指定用户名 # -p 指定密码(建议不在命令行中直接写密码) mysql -h[ip] -u[user] -p
-
-
身份验证:
- 连接器会验证用户名和密码。
- 如果验证失败,返回错误信息并断开连接。
- 如果验证成功,连接器会获取该用户的权限,并保存起来。
-
连接管理:
-
可以通过
SHOW PROCESSLIST
查看当前连接的客户端信息。 -
空闲连接会根据
wait_timeout
参数自动断开(默认 8 小时)。SHOW VARIABLES LIKE 'wait_timeout';
-
可以手动断开空闲连接:
KILL CONNECTION [id];
-
MySQL 支持的最大连接数由
max_connections
参数控制。SHOW VARIABLES LIKE 'max_connections';
-
第二步:查询缓存(MySQL 8.0 已删除)
-
查询缓存机制:
- 查询缓存以
key-value
形式保存在内存中,key
是 SQL 查询语句,value
是查询结果。 - 如果查询语句命中查询缓存,直接返回结果。
- 如果未命中,则继续后续流程,并将结果存入查询缓存。
- 查询缓存以
-
查询缓存的局限性:
- 对于更新频繁的表,查询缓存的命中率很低。
- 表的任何更新操作都会清空该表的查询缓存。
- MySQL 8.0 版本移除了查询缓存模块。
第三步:解析 SQL
-
解析器的作用:
-
对 SQL 语句进行词法分析和语法分析。
-
词法分析:识别关键字(如
SELECT
、FROM
)和非关键字(如表名、字段名)。 -
语法分析:根据语法规则判断 SQL 是否合法,并构建语法树。
-- 示例 SQL SELECT username FROM userinfo; -- 词法分析结果: -- 关键字:SELECT, FROM -- 非关键字:username, userinfo
-
注意:解析器只负责语法检查,不会检查表或字段是否存在。
-
第四步:执行 SQL
执行 SQL 查询语句分为三个阶段:
-
预处理阶段:
- 检查表或字段是否存在。
- 将
SELECT *
中的*
符号扩展为表上的所有列。
-- 示例:表不存在的情况 SELECT * FROM test; -- 错误信息:ERROR 1146 (42S02): Table 'mysql.test' doesn't exist
-
优化阶段:
-
优化器根据查询成本选择最佳的执行计划。
-
例如,选择使用哪个索引(如果有多个索引)。
-
可以通过
EXPLAIN
查看执行计划:EXPLAIN SELECT id FROM product WHERE id > 1 AND name LIKE 'i%';
-
-
执行阶段:
-
执行器根据执行计划从存储引擎读取记录,并返回给客户端。
-
执行器与存储引擎的交互过程如下:
-
主键索引查询:
SELECT * FROM product WHERE id = 1;
- 执行器调用存储引擎的接口,定位到主键索引的记录。
- 存储引擎返回记录给执行器,执行器判断是否符合查询条件。
-
全表扫描:
SELECT * FROM product WHERE name = 'iphone';
- 执行器调用存储引擎的全表扫描接口。
- 存储引擎逐条返回记录,执行器判断是否符合查询条件。
-
索引下推(Index Condition Pushdown, ICP) :
SELECT * FROM t_user WHERE age > 20 AND reward = 100000;
- 优化器将部分条件下推到存储引擎层,减少回表操作。
- 存储引擎在索引中过滤满足条件的记录后,再执行回表操作。
-
-
总结
执行一条 SELECT
查询语句的完整流程包括:
-
连接器:建立连接、管理连接、校验用户身份。
-
查询缓存:检查查询缓存(MySQL 8.0 已移除)。
-
解析 SQL:进行词法分析和语法分析,构建语法树。
-
执行 SQL:
- 预处理:检查表或字段是否存在,扩展
SELECT *
。 - 优化:选择最佳执行计划。
- 执行:从存储引擎读取记录并返回结果。
- 预处理:检查表或字段是否存在,扩展