news 2026/4/15 22:23:34

一条 SELECT 语句在 MySQL 中是如何执行的?—— 从 TCP 连接到结果返回的完整链路解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一条 SELECT 语句在 MySQL 中是如何执行的?—— 从 TCP 连接到结果返回的完整链路解析

引言

本文从底层视角详细解析了一条 SELECT 语句在 MySQL 中的完整执行流程,涵盖连接建立、查询缓存、SQL 解析、执行计划生成以及执行器与存储引擎的协作机制,深入解释了 MySQL 优化器的工作原理和关键设计取舍,适合作为理解 MySQL 内核执行机制和面试高频题的系统性参考。

为什么要搞懂 SELECT 的执行过程?

在日常开发中,我们几乎每天都在写SELECT语句,但大多数人只停留在“会写 SQL”这个层面:

SELECT * FROM user WHERE id = 1;

但在实际中,或者在性能优化、慢 SQL 排查、数据库异常分析时,更应该关心的是:

  • MySQL是如何处理这条 SQL 的?
  • SQL 在 MySQL 内部经历了哪些模块?
  • 优化器是如何选择索引的?
  • 为什么EXPLAIN能看到执行计划?
  • 为什么 MySQL 8.0 直接移除了查询缓存?

理解一条 SELECT 的执行流程,是理解 MySQL 内核的起点。

整体执行流程总览

一条SELECT语句,在 MySQL 中大致会经历以下几个阶段:

  1. 连接器(Connection)

  2. 查询缓存(Query Cache,8.0 已移除)

  3. 解析器(Parser)

    • 词法分析

    • 语法分析

  4. 执行器阶段

    • 预处理(Prepare)

    • 优化(Optimize)

    • 执行(Execute)

下面我们按时间顺序逐层拆解

第一步:连接器 —— 建立客户端与 MySQL 的连接

MySQL 是如何被连接的?

当你在 Linux 或 macOS 终端执行:

mysql -h 127.0.0.1 -u root -p

本质上发生了以下事情:

(1)TCP 三次握手

MySQL基于 TCP 协议通信,客户端与 MySQL Server 之间会先完成 TCP 三次握手:

客户端 -> SYN 服务端 -> SYN + ACK 客户端 -> ACK

连接成功后,才进入 MySQL 协议层。

(2)身份认证

连接器会做以下校验:

  • 校验用户名
  • 校验密码
  • 校验来源主机
  • 加载该用户的权限信息

这些权限信息会在连接建立时一次性读取

⚠️重要细节

即使你在连接后修改了用户权限,这个连接内的权限也不会立刻生效,需要重新建立连接。

(3)连接管理

  • 每个连接对应一个线程

  • 连接数受max_connections控制

  • 连接长期不释放,会导致连接资源浪费

第二步:查询缓存(Query Cache)—— 已被淘汰的设计

⚠️ MySQL 8.0已经彻底移除查询缓存

但理解它为什么失败,非常有价值。

查询缓存的设计思路

查询缓存采用Key-Value形式:

  • Key:SQL 字符串(完全一致)

  • Value:查询结果集

流程是:

收到 SQL → 判断是否命中缓存 → 命中:直接返回结果 → 未命中:继续执行 SQL

为什么查询缓存命中率极低?

举个例子:

SELECT * FROM user WHERE id = 1; SELECT * FROM user WHERE id=1;

哪怕只是一个空格不同,缓存都无法复用。

更致命的是:

  • 只要表有任何一条数据发生变化
  • 该表相关的缓存全部失效

在高并发、频繁写入的系统中:

查询缓存 = 缓存了个寂寞

为什么 MySQL 8.0 移除了它?

  • 维护成本高
  • 锁竞争严重
  • 实际收益极低

结论:

查询缓存是一个“设计上很美好,实践中很失败”的功能。

第三步:解析器 —— SQL 是如何被“看懂”的?

解析器负责把字符串形式的 SQL,转成 MySQL 能理解的结构

词法分析(Lexical Analysis)

将 SQL 字符流拆分成一个个Token

示例 SQL:

SELECT name FROM user WHERE id = 1;

词法分析后大致得到:

Token 类型内容
KEYWORDSELECT
IDENTIFIERname
KEYWORDFROM
IDENTIFIERuser
KEYWORDWHERE
IDENTIFIERid
OPERATOR=
NUMBER1

语法分析(Syntax Analysis)

在词法分析的基础上,解析器会:

  • 校验 SQL 是否符合 MySQL 语法规则
  • 构建语法树(AST,Abstract Syntax Tree)

如果 SQL 不合法,例如:

SELEC name FROM user;

会直接在这一步报错:

You have an error in your SQL syntax

第四步:执行 SQL(核心)

真正“干活”的阶段,分为三步:

Prepare → Optimize → Execute

Prepare:预处理阶段

主要做静态检查

  • 表是否存在
  • 字段是否存在
  • 权限是否满足
  • SELECT *展开为具体字段

例如:

SELECT * FROM user;

会被展开为:

SELECT id, name, age, email FROM user;

Optimize:优化器阶段(灵魂)

优化器做什么?
  • 选择使用哪个索引
  • 决定表的访问顺序
  • 判断是否使用:
  • 全表扫描

  • 索引扫描

  • 覆盖索引

成本模型

MySQL 优化器是基于成本(Cost)的:

  • I/O 成本
  • CPU 成本
  • 预估扫描行数

最终选择成本最低的执行计划

使用 EXPLAIN 查看执行计划
EXPLAIN SELECT * FROM user WHERE id = 1;

常见字段含义:

字段含义
type访问方式(const、ref、range、ALL)
key实际使用的索引
rows预估扫描行数
Extra额外信息(Using index、Using filesort)

Execute:执行器阶段

执行器根据优化器生成的执行计划:

  • 调用存储引擎接口(如 InnoDB)
  • 按索引或全表扫描读取数据
  • 逐行判断WHERE条件
  • 返回结果给客户端

总结:一条 SELECT 的完整生命周期

客户端 ↓ TCP 连接 + 身份认证(连接器) ↓ 查询缓存(8.0 已移除) ↓ 解析器(词法 + 语法) ↓ 预处理(表、字段、权限) ↓ 优化器(选择索引、执行计划) ↓ 执行器(调用存储引擎) ↓ 返回结果
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/13 0:02:20

玩转 Flutter 自定义 Painter:从零打造丝滑的仪表盘动效与可视化图表

欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。 在 Flutter 开发中,原生组件往往难以满足个性化的视觉需求 —— 比如电商 APP 的销量仪表盘、金融 APP 的收益走势图、健身 APP 的运…

作者头像 李华
网站建设 2026/4/16 13:53:11

FP8入门指南:零基础用快马体验AI高效计算

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 为初学者设计一个FP8学习项目,包含:1. FP8基本概念解释(交互式笔记);2. 简单的FP8矩阵计算示例;3. 可视化FP8…

作者头像 李华
网站建设 2026/4/16 14:29:21

MinIO隐性成本:企业禁用的经济账

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发MinIO总拥有成本计算器,要求:1. 支持输入节点规模、数据量等参数 2. 计算3年期的硬件/人力/带宽成本 3. 与阿里云OSS等方案进行成本对比 4. 生成成本效益…

作者头像 李华
网站建设 2026/4/16 12:20:38

10倍效率!用AI工具开发Chrome插件全流程对比

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个对比传统开发和AI辅助开发Chrome插件的示例项目。功能是网页截图工具插件,需要:1) 截图当前页面或选区 2) 添加标注工具 3) 导出PNG/PDF 4) 历史记录…

作者头像 李华
网站建设 2026/4/16 14:00:08

Vue3 Teleport实战:构建全屏加载动画组件

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个使用Vue3 Teleport的全屏加载组件。功能需求:1. 当API请求时显示全屏半透明遮罩 2. 中央显示旋转的加载图标 3. 自动隐藏错误和完成状态 4. 支持自定义加载文字…

作者头像 李华
网站建设 2026/4/15 21:35:04

教程4:预制的使用-–-behaviac

原文 本文档描述的是3.6及以后版本,对于3.5及以前的老版本请参考分类“3.5”。预制(Prefab)可以用来复用和实例化已有的行为树,如果只是直接复用行为树,预制跟引用子树的功能是一样的。 但是预制还可以用来定制个别节…

作者头像 李华