当前位置: 首页 > 科技观察

MySQL系列执行SQL语句会发生什么?

时间:2023-03-13 20:46:10 科技观察

前言当我们使用navicat、mysqlworkbench等mysql客户端执行一条sql语句时,可以得到相应的结果。例如:那么在这个过程中发生了什么?执行sql是一个Rpc调用。mysql是一种客户端-服务器架构。我们平时使用的大部分程序app其实都是由两部分组成的,一个是客户端程序,一个是服务端程序。以我们常用的微信和QQ为例。客户端安装在我们的手机里,服务端运行在机房的服务器里。我们在发送消息时,通常会使用客户端和服务端进行通信。比如你和女朋友发消息的过程:消息经过客户端打包,添加发送方和接收方信息,然后从你的微信客户端发送到微信服务器;微信服务器从消息中获取其发送消息的接收者信息,将这条消息发送给女友的微信客户端,女友的微信客户端会显示你给他发了消息。mysql的使用过程和这个一样。它的服务端程序直接和我们存储的数据打交道,然后很多客户端程序可以连接到这个服务端程序,发送增删改查的请求,然后服务端响应这些请求,从而操作它维护的数据.主要流程如下:因此,一条sql的执行就是一次rpc调用。以后有时间我也会分享RPC相关的东西,大家一起交流学习!服务器如何处理客户端请求?无论我们使用什么样的客户端和服务器进程进行通信,最终的效果都是:客户端进程发送一段文本(MySQL语句)给服务器进程,再发送一段文本(处理结果)给客户端进程在服务器进程处理它之后。主要流程如下:从图中我们可以看出,服务端程序需要经过三个部分来处理来自客户端的查询请求,即连接管理、分析优化与执行、存储引擎。其中,连接管理、分析优化和执行往往被划分到mysql的server层。连接管理客户端进程可以通过多种方式之一建立与服务器进程的连接,例如TCP/IP、命名管道或共享内存,或Unix域套接字。连接管理也采用了池化技术:每当客户端进程连接到服务器进程时,服务器进程会创建一个线程专门处理与客户端的交互,当客户端退出连接时会断开与服务器的连接,服务器端则不会立即销毁与客户端交互的线程,但缓存它,并在另一个新客户端再次连接时将缓存的线程分配给新客户端。这具有不频繁创建和销毁线程的效果,从而节省了开销。由于表更新频繁,查询缓存也频繁更新,查询缓存失败的情况也很频繁,所以查询缓存的优点往往大于缺点,MySQL8.0版本直接删除了querycache的全部功能。语法分析如果查询缓存没有命中,下一步就是进入正式查询阶段。由于客户端程序发送的请求只是一段文本,MySQL服务器程序首先要对文本进行分析判断请求的语法是否正确,然后从文本中提取出要查询的表和各种查询条件并把它们放在MySQL服务器内部使用的一些数据结构中。解析查询优化后,MySQL知道您要做什么。在开始执行之前,必须经过查询优化处理。优化处理是指当一个表有多个索引时,决定使用哪个索引;或者当一个语句有多个表关联(join)时,决定每个表的连接顺序。我们可以使用EXPLAIN语句来查看一条语句的执行计划。大多数优化逻辑是基于成本的优化。MySQL中一条查询语句的执行成本由两方面组成:I/O成本:从磁盘加载到内存过程中损失的时间称为I/O成本。CPU成本:读取记录是否满足相应的查找条件,对结果集进行排序等所花费的时间称为CPU成本。对于InnoDB存储引擎,mysql规定默认读取一页的代价为1.0,默认读取并检查一条记录是否满足搜索条件的代价为0.2。以单表查询为例,成本计算步骤如下:根据搜索条件,找到所有可能的索引,计算全表扫描的成本计算使用不同索引执行查询的成本比较各种成本执行计划找到成本最低的那个。存储引擎直到服务器程序完成查询优化,才真正访问到真正的数据表。MySQL服务器将数据存储和提取操作封装到一个称为存储引擎的模块中。我们知道一个表是由一行行的记录组成的,但这只是一个逻辑概念。如何在物理上表示记录,如何从表中读取数据,如何将数据写入具体的物理存储,都是存储引擎负责的事情。为了实现不同的功能,MySQL提供了多种存储引擎。不同存储引擎管理的表的具体存储结构可能不同,采用的访问算法也可能不同。大多数人为了管理方便,将不涉及真正数据存储的连接管理、查询缓存、语法分析、查询优化等功能划分到MySQL服务器的功能中,将真正访问数据的功能划分到MySQL服务器的功能中。存储引擎。ExecutorExecutor是各种不同的存储引擎,它们向上层的MySQL服务器提供统一的调用接口(即存储引擎API),包括几十个底层函数,比如“读取索引的第一个内容”,“读取索引的下一个内容”、“插入记录”等。比如执行一个查询sql,在开始执行的时候,首先要判断自己是否有对这张表执行查询的权限。如果没有,则返回没有权限的错误;在我们一开始的例子中,id字段是没有索引的,那么executor的执行过程是这样的:调用InnoDB引擎接口获取这张表的第一行,判断id值是否为10,如果不是,跳过它,如果是,将这一行保存在结果集中;调用引擎接口获取“Nextrow”,重复相同的判断逻辑,直到取出表的最后一行。执行器将上述遍历过程中满足条件的所有行组成的记录集作为结果集返回给客户端。对于有索引的表,执行逻辑类似。首先调用的是“获取满足条件的第一行”接口,然后循环获取“满足条件的下一行”接口。这些接口已经在引擎中定义。但是对于sql语句的插入、删除、修改,还涉及到redolog、undolog、binlog的操作。我们有时间再谈这个。因此,你只需要根据生成的执行计划,调用底层存储引擎提供的API(executor),获取数据后返回给客户端即可。执行一条sql语句。