MySQL中一条SQL语句的执行流程
执行流程
MySQL 中的一条 SQL 语句在执行时,会走的流程如下图所示:

从上图图中可以看出,MySQL 中一条 SQL 语句会经过连接器、分析器、优化器、执行器这些步骤,然后从存储引擎获取数据,最终返回。
图中的“查询缓存”步骤因为版本的更迭被丢弃掉了。
大体来说,MySQL 可以分为 Server 层和存储引擎层这两部分。
Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。
连接器
连接器,顾名思义,负责跟客户端建立连接、获取权限、维持和管理连接的。
通常使用以下命令去连接:
1 | |
输完命令之后,你就需要在交互对话里面输入密码。虽然密码也可以直接跟在 -p 后面写在命令行中,但这样可能会导致密码泄露。
分析器
首先,MySQL 需要知道你要做什么,因此需要对 SQL 语句做解析。
分析器,负责对输入进来的 SQL 语句进行词法分析,判断 SQL 语句中的字符串分别是什么,代表着什么。
1 | |
MySQL 从你输入的”select”这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”,
如果语句中的 T 不存在或者 ID 列不存在,会直接抛出错误。
做完了这些识别以后,就要做“语法分析”。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。
在这一步中会判断语句中的数据表和数据列是否存在, 别名是否有歧义等语法错误,如果存在语法错误就会收到 “You have an error in your SQL syntax” 的错误提醒。
通过词法分析和语法分析,通过的话就代表 SQL 语句是一个满足语法的 SQL 语句,下一步就会交给优化器。
优化器
经过了分析器,MySQL 就知道你要做什么了。在开始执行之前,还要先经过优化器的处理。
优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。比如你执行下面这样的语句,这个语句是执行两个表的 join:
1 | |
- 既可以先从表 t1 里面取出 c=10 的记录的 ID 值,再根据 ID 值关联到表 t2,再判断 t2 里面 d 的值是否等于 20。
- 也可以先从表 t2 里面取出 d=20 的记录的 ID 值,再根据 ID 值关联到 t1,再判断 t1 里面 c 的值是否等于 10。
这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。
优化器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。
执行器
MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。
开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下代码所示:
1 | |
如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
比如我们这个例子中的表 T 中,ID 字段没有索引,那么执行器的执行流程是这样的:
- 调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 10,如果不是则跳过,如果是则将这行存在结果集中;
- 调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
- 执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
至此,这个语句就执行完成了。
对于有索引的表,执行的逻辑也差不多。
小结
在 MySQL 中,一条 SQL 语句执行时会经历以下步骤:
- 连接器:用于创建与 MySQL 数据库的连接并且管理;
- 分析器:用于解析 SQL 语句,判断 SQL 语句是否存在语法错误;
- 优化器:选择执行 SQL 语句的最佳方案(存在多个索引时最终使用哪个索引);
- 执行器:调用具体存储引擎所提供的读写接口,获取数据并返回。