SQL语句执行过程

MySQL架构

MySQL架构如下:
MySQL架构

MySQL架构共分为两层:

  • Server层:负责建立连接、分析和执行SQL。
  • 存储引擎层:复杂数据的存储和提取。

MySQL的几个重要组件:

  • 连接器:负责处理客户端连接。
  • 查询缓存:缓存查询结果以提高性能。
  • 解析器:解析SQL语句,生成查询计划。
  • 优化器:优化查询计划以提高执行效率。
  • 执行器:执行查询计划并返回结果。

连接器

连接器主要负责连接MySQL服务,然后才能执行SQL语句。

连接命令:

1
mysql -h localhost -u root -p

MySQL是基于TCP协议的,所以连接时需要经过TCP三次握手过程,断开连接时需要经过TCP四次挥手过程。

常用参数:

  • wait_timeout:空闲连接最大空闲时长,默认值为8小时。
  • max_connections:最大连接数,默认值为151。

MySQL连接也分为长连接和短连接,但长连接有可能会占用内存过大导致MySQL服务异常重启。
解决办法:

  • 定期断开长连接。
  • 客户端主动重置连接。

连接器总结:

  • 与客户端进行TCP三次握手建立连接。
  • 校验客户端的用户名和密码,如果不对则报错。
  • 如果对,读取该用户权限,后面的权限逻辑判断都基于此时的权限。

查询缓存

查询缓存以key-value的形式存储查询结果,key是SQL查询语句,value是查询结果。

但对于更新频繁的表,查询缓存的命中率较低,因为每次更新都会导致相关缓存被清空。

所以,MySQL8.0版本已经废弃了查询缓存功能。8.0之前的版本可以通过参数query_cache_type设置成DEMAND来关闭查询缓存。


解析器

解析器负责将SQL语句解析成MySQL能够理解的格式,生成查询计划。主要做两件事:

  • 词法分析
  • 语法分析

词法分析

词法分析将SQL语句分解成一个个的词法单元(token),每个token代表SQL语句中的一个基本元素,如关键字、标识符、操作符等。

如下SQL语句:

1
select name from user;

词法分析的结果如下:

关键字 非关键字 关键字 非关键字
select name from user

语法分析

语法分析将词法分析的结果根据语法规则判断是否满足MySQL语法,没问题就会构建出SQL语法树,方便后续获取SQL类型、表名、字段名等信息。

SQL语法树

注意:解析器只负责检查语法和构建语法树,不会去查表或者字段存不存在。


执行SQL

执行SQL主要分为三步:

  • prepare阶段:预处理阶段。
  • optimize阶段:优化阶段。
  • execute阶段:执行阶段。

预处理器

prepare阶段主要做两件事:

  • 检查SQL语句中的表或者字段是否存在。
  • select *中的*扩展为表上的所有列。

优化器

优化器主要负责确定SQL查询语句执行方案,比如选择哪个索引、使用什么连接方式等。

可以通过explain命令查看SQL语句的执行计划。

执行器

执行器根据优化器生成的执行计划来执行SQL语句,最终返回结果给客户端。


总结

执行一条SQL查询语句的过程如下:

  • 连接器:建立连接,校验用户名和密码,读取权限。

  • 查询缓存:如果查询缓存命中,则直接返回结果,否则继续执行。MySQL8.0版本已经废弃了查询缓存功能。

  • 解析器SQL,通过解释器对SQL语句进行词法和语法分析,构建语法树。

  • 执行SQL,共有三个阶段:

    • 预处理阶段:检查表和字段是否存在,扩展select *中的*
    • 优化阶段:确定SQL查询语句执行方案。
    • 执行阶段:根据优化器生成的执行计划来执行SQL语句,最终返回结果给客户端。
  • 查询语句的执行流程如下:权限校验(如果命中缓存)—>查询缓存—>分析器—>优化器—>权限校验—>执行器—>引擎

  • 更新语句执行流程如下:分析器---->权限校验---->执行器—>引擎—redo log(prepare 状态)—>binlog—>redo log(commit 状态)