MySQL学习之一条SQL查询语句的执行

文章目录

  • 前言
  • 一、MySQL基础架构
  • 二、连接器
  • 三、查询缓存
  • 四、分析器
  • 五、优化器
  • 六、执行器


前言

今天我们通过一条SQL查询语句的执行过程,来剖析MySQL的基础架构。让我们从宏观上先有一个对MySQL的认识与了解


一、MySQL基础架构

首先,我们要对MySQL的整体架构了解下,然后才能对每个部分进行突破。
MySQL的整体架构示意图如下:
MySQL学习之一条SQL查询语句的执行_第1张图片
由图可以看出,MySQL大体分为Server层和存储引擎层两部分。
其中,Server层包括连接器、查询缓存、分析器、优化器、执行器等。对于所有的内置函数(如日期、时间、数学和加密函数等),所有的跨存储引擎的功能都在这一层实现,如存储过程、触发器、视图等。

存储引擎层负责数据的存储和提取,默认使用的引擎是InnoDB。

对整体架构有了连接之后,接下来我们深入学习下每个组件的具体作用

二、连接器

连接器负责跟客户端建立连接、获取权限、维持和管理连接。
连接命令如下:

mysql -h$ip -P$port -u$user -p密码

在完成TCP握手后,连接器就开始认证身份,此时会出现两种情况:

  • 用户或密码不对,就会收到“Access denied for user”的错误,然后客户端程序结束执行
  • 用户密码认证通过,然后连接器会到权限表里面查询所拥有的的权限,连接里面的权限判断逻辑都将会依赖此时读到的权限。即使用管理员账号对这个用户权限做了修改,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置

连接完成后,我们可以通过如下命令:

show processlist;

来查看每个连接的状态
MySQL学习之一条SQL查询语句的执行_第2张图片
其中,Command列显示为“Sleep”的表示该连接为空闲连接。

如果长时间未使用这个连接,连接器就会自动断开。这个时间由参数wait_timeout控制,默认值是8小时。

此时断开之后,突然客户端如果发送请求时,就会收到错误提醒,如果真要发送请求只能重连然后再继续执行请求了。

对于说的这8小时,这么长,是不是想到了经常在写http或者tcp网络编程程序时听别人说的长连接啊。
在数据库里,长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。

建立连接的过程比较复杂,tcp三次握手,身份认证,权限认证等等操作,如果总是频繁的断开连接,建立连接,这就无可避免的增加了很多性能的损耗。因此为了避免这种损耗,尽量使用长连接。但是如果全部采用长连接,也会出现问题,有时候会导致MySQL占用内存涨的特别快,这是因为MySQL在执行过程中临时使用的内存是管理在连接对象里面的,这些资源只会在连接断开的时候才释放,因此长连接长期的积累,肯定会导致内存占用变大。

为了解决这个问题,有两种方案可以采用:

  • 定期断开长连接,使用一段时间,或者程序里面判断执行过一个占用内存很大查询后,断开连接,之后要查询再重连
  • 可以在每次执行一个比较大的操作后,通过执行mysql_reset_connection来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。

了解完了连接器后,接下来再了解下查询缓存

三、查询缓存

MySQL拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。
之前执行过的语句及其结果可能以key—value的形式缓存在内存中,key是查询语句,value是对应的查询结果。
首先直接向缓存中查询一遍,看似比直接向磁盘中查询快。但是大多数情况下,不建议使用查询缓存,因为查询缓存往往弊大于利

因为如果我们对一个表更新,那么这个表上所有的查询缓存都会被清空,因此对于一个更新大的数据库来说,查询缓存的命中率会非常低。除非有一张静态表,很长时间才会更新一次,那这张表上的查询才适合使用查询缓存。

四、分析器

分析器会对SQL语句进行解析。
分析器主要会进行词法分析和语法分析
(确定要做什么)

五、优化器

这里主要介绍下优化器的主要工作。优化器是在表里有多个索引或者进行多表查询时,根据计算的时间成本,选择执行的索引或者查表的顺序,选择最优的操作,确定执行方案。
对于是怎么计算成本,进行方案选择的,可以看我写的那个mysql是怎么运行的里面有具体总结,也可以看后面的文章

六、执行器

执行器用于执行语句。
首先判断对这个表有没有执行权限,如果没有就返回没有权限的错误,如果有就打开表继续执行,打开表的时候会根据表的引擎定义,去使用这个引擎提供的接口。

接下来我们以这个查询语句为例(ID字段没有索引):

select * from T where ID=10;

执行器的流程如下:

  1. 调用InnoDB引擎接口取这个表的第一行,判断ID值是不是10,如果不是则跳过,如果是则将这行存在结果集中;
  2. 调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行
  3. 执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端

对于有索引的表,执行逻辑也差不多。第一次调用的是“取满足条件的第一行”这个接口,之后循环取“满足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。

到此我们对,MySQL的基础架构有了初步了解。接下来我们将会对其内部原理进行深入的学习,请看后面博客更新

你可能感兴趣的:(sql,mysql,学习,sql)