掌握 MySQL 中 SQL 语句的执行过程

作为开发人员都非常清楚,当我们写好一个 sql 语句之后,连接到数据库点击执行,数据库就会返回我们要查询或者更新的结果。但是,数据库服务器在接收到一个 sql 请求后内部是如何处理的,可能就不太清楚了。这一节主要为大家讲解从客户端发起一个 sql 语句的查询,数据库服务器内部的一个处理流程。

从下面的一个 MySQL 请求的处理流程图中可以看出,MySQL 的处理流程主要分为4个步骤:客户端与服务端通信、查询优化处理过程、查询执行引擎、返回结果给客户端

0b7f50c189c5174d66f99e887384543c.png

1、客户端与服务端通信

一般通信方式有3种:单工,半双工,全双工。单工就是只能单向传输,要么A端给B端传输,要么B端给A端传输;半双工是可以双向传输的,但是同一时间只能是一个方向传输,也就是说A端给B端传输的时候,B端只能等待,反过来也一样,B端给A端传输的时候,A端也只能等待;全双工是双向随便传输。

MySQL 客户端与服务器的通信方式是半双工的,也就是说,我们的一个数据库连接在向数据库发送数据的时候,此时这个数据库连接是不能给客户端返回数据的,一定是数据返回完毕以后,客户端才能再次发起查询操作。这也就是我们在做数据查询的时候用 where 条件 和 limit 限制数据结果行数的原因,否则客户端连接需要等到数据库把所有的查询结果返回之后,才能进行下一个操作。

从上面的分析可以看出,MySQL 数据库半双工通信模式的一个重要特点是:客户端一旦开始发送指令,服务端需要接收完毕才能响应,客户端只有在完全接收到服务端响应的数据后,才能再次发送指令。有点像对讲机,这就是为什么电视里看到两个人对讲时,最后要说一句 over 的原因,当听到 over 的时候,另一端的人就可以按对讲键进行说话了。我们在程序开发中,一般会用多个连接进行数据交互,通过数据库连接池来进行管理,因此对这块体会可能不够深刻。

其实 MySQL 的每一个连接都有其对应的状态来标识它目前所处的阶段,和线程类似,我们可以通过下面的命令查看数据库连接的状态:

SHOW [FULL] PROCESSLIST ;

常用的几个状态描述:

序号
状态值  状态描述
1 login  连接线程的初始状态,直到客户端已成功通过身份验证
2
executing 该线程已开始执行一条语句    
3 optimizing 服务器正在对查询执行初始优化
4 Updating 线程正在搜索或者更新要更新的行  
5 Sending data 正在将数据发送到客户端,一般会执行大量的磁盘访问操作
6 Sorting result 正在对结果排序   
7 Waiting for commit lock 正在等待提交锁  

当发现数据库连接长时间占用的时候,可以用 kill 命令杀死线程:

KILL processlist_id ;

2、查询优化处理过程

解析器解析 sql 语句:通过 lex 词法分析器(就是把一个完整的 SQL 语句分析成独立的单词  )、yacc 语法分析器(就是分析是否符合语法规则,比如单引号是否闭合等)进行分析,将 sql 语句按 sql 标准解析成 解析树(select_lex)对象,主要功能是把一个 sql 语句的字符串解析成数据库服务器可以处理的解析树对象,便于后续进行预处理和生成执行计划。

预处理:预处理会根据 mysql 的语法规则对解析树对象进行合法性检查,比如检查表名列名是否存在、检查名字和别名,保证没有歧义,预处理之后得到一个新的解析树。

优化器生成执行计划:优化器的主要作用就是把这个 sql 语句找到最优的执行计划,MySQL 的查询优化器和 Oracle 类似,都是基于成本的计算,优化器会尝试使用不同的执行计划,以便于找到一个最优的执行计划(一般随机读取4K的数据库进行分析)。

可以使用以下的命令查看查询的成本:

show status like 'Last_query_cost';

优化器最终会把解析树变成一个查询执行计划。MySQL 提供了一个执行计划的工具,我们在 SQL 语句前面加上 EXPLAIN,就可以看到执行计划的信息。我们在做 sql 调优的时候主要也就是对这部分进行处理。

3、查询执行引擎

查询执行模块,也就是查询执行引擎,根据优化器生成的最优执行计划调用对应存储引擎的 API 的进行执行计划的执行,并获取查询应该返回的结果集。

4、返回结果给客户端

如果没有开启缓存,把查询到的结果集返回到客户端;如果开启了缓存,执行缓存操作,把结果集存入缓存,然后把结果返回给客户端,即使结果集是空的,也要返回。

后面将为大家介绍 MySQL 的缓存

相关推荐

  1. MySQL内部机制:SQL语句执行过程浅析

    2024-07-18 16:34:04       36 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-18 16:34:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-18 16:34:04       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-18 16:34:04       58 阅读
  4. Python语言-面向对象

    2024-07-18 16:34:04       69 阅读

热门阅读

  1. linux修改时区为CST

    2024-07-18 16:34:04       18 阅读
  2. 请求通过Spring Cloud Gateway 503

    2024-07-18 16:34:04       19 阅读
  3. 使用小皮面版的Nginx服务搭建本地服务器

    2024-07-18 16:34:04       22 阅读
  4. Jenkins 安装、部署与配置

    2024-07-18 16:34:04       24 阅读
  5. Nginx:502 Bad Gateway 错误的原因及解决方法

    2024-07-18 16:34:04       19 阅读
  6. Web开发-LinuxGit基础5-本地-分支

    2024-07-18 16:34:04       21 阅读
  7. 交易-软件科技股F4(kafka、NET、snow、MongoDB)

    2024-07-18 16:34:04       21 阅读
  8. 关于Hadoop生态系统一部分的Catalog

    2024-07-18 16:34:04       25 阅读
  9. 高内聚,低耦合的解释及实例【包学包会】

    2024-07-18 16:34:04       21 阅读
  10. 网页制作技术:概念、现状与展望?

    2024-07-18 16:34:04       21 阅读
  11. Ubuntu22.04:安装Samba

    2024-07-18 16:34:04       22 阅读
  12. 使用 Vue 和 ECharts 打造动态数据可视化图表

    2024-07-18 16:34:04       25 阅读
  13. 排序思想-快排

    2024-07-18 16:34:04       25 阅读
  14. pytorch学习(一)argparse

    2024-07-18 16:34:04       24 阅读
  15. logback-spring.xml配置

    2024-07-18 16:34:04       18 阅读