【MySQL数据库】你知道一条SQL语句是怎么执行的吗?

在学习了MySQL的简单基础的操作之后,就想更加深入的了解数据库。发现了一个看似很基础的问题:一条MySQL语句是怎么执行的呢?这一问到把自己问了个懵,好像只知道怎么写SQL语句,不知道自己在执行的背后到底发生了什么。充满疑问的学习之后,也初步理解了SQL语句的执行流程,本文用较为通俗的语言来为大家讲解,参考极客时间的《MySQL实战45讲》的内容。

一、基本架构示意图

在这里插入图片描述
以上,就是MySQL的基本架构图。简单的来说包含了sever层存储引擎层。其中sever层中包含了连接器、查询缓存、分析器、优化器和执行器。而存储引擎负责数据的存储和提取。
简单的写了它们各自的作用,接下来使用例子来一步步认识每一个部件。

二、各个部件

1.连接器

在使用数据库开始前,首先我们要连接到这个数据库中。只有连接上才能进行后续的操作,这个时候使用的部件就是连接器。连接器负责和客户端建立连接、获取权限、维持和管理权限
连接命令一般是这样写的:

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

这一步相信大家都操作过,接下来就是根据输入用户可能会要求输入密码。

  • 如果输入密码有误,就会报一个"Access denied for user"的错误。
  • 如果输入正确,就连接上该数据库,此时连接器会查询到你所拥有的权限,此后的操作都基于该权限,如果在使用中修改权限,那么修改后的权限只会在下一次重新建立的连接中生效。

连接完成后,可以使用 show processlist语句查看已经建立好的连接以及对应的状态。
如果连接好后,我们很久没有继续操作,那么它就会自动断开连接,默认时间为8小时。断开后如果在想对这个数据库进行操作,就必须进行重连。

接下来介绍两个名词:长连接和短链接

  • 长连接:连接成功后,客户端一直持续有操作,那么将一直使用同一个连接
  • 短连接:连接成功后,每次只执行几句SQL语句就断开连接

短连接的使用会经常经历建立连接的复杂过程,因此我们建议使用长连接,而长连接的使用会使内存涨的特别快。那么有没有一个解决的方法呢?

  1. 定期断开长连接,使用一段时间或者执行过一个占用内存较大的查询后,就断开连接,之后查询时再重新连接。
  2. MySQL 5.7或更新版本,可以在每次执行过一个较大操作后,执行mysql_reset_connection来重新初始化连接,这个过程不需要重新登录但会恢复到连接刚创建完后的状态

2.查询缓存

创建连接后,就可以执行select语句了,这时候就会到达查询缓存这一步:
MySQL拿到一个语句后,会首先判断之前是否执行过这条语句,如果执行过,MySQL的缓存中就可能会以key-value形式出现该结果,key表示查询语句,value表示结果集。如果查询到缓存中存在对应的key那么就直接返回其value结果集。如果命中缓存,执行速度非常快,反之如果不存在缓存中就继续执行接下来的操作,成功后还会将新的结果集保存到缓存中。
但注意,缓存的失效非常快,只要对该表上有一个更新操作,那么之前的缓存全都要被清空。因此只有在更新次数少的表亦或者是长时间更新一次的表中才适合使用查询缓存。

3.分析器

走到分析器就表示没有命中缓存,顾名思义,分析器就是用来分析的,分析什么呢?先执行时要知道SQL语句具体是准备干什么,所以当然是分析输入的MySQL语句准备 “ 做什么?”因此对SQL语句进行解析。其中包含词法分析和语法分析

  • 词法分析:由于输入的语句都是由一堆字符串以及空格构成的,所以,首先要对字符串中的每一个词的含义都识别出来,比如操作、列名、表名等
  • 语法分析:解析完词后,分析器会整体看该语句是否满足语法规则,如果错误返回错误信息。

4.优化器

通过分析器,我们知道了SQL语句准备完成的任务,但MySQL不会一味的直接执行,而是会通过优化器来对SQL语句进行优化操作。具体体现在:

  • 在多个索引中选择要使用的索引
  • 在多个表进行连接时,在不改变语句的执行逻辑顺序的前提下,决定连接的顺序

通过连接器,在优化后可以更好地提升执行语句的效率。

5.执行器

在使用分析器之道的语句要“做什么”,使用优化器知道了语句该“怎么做”后,我们就要开始真正的执行这个语句,这时候就到了执行器。
开始执行时,首先判断你对这个表是否拥有操作权限。如果没有就返回没有权限的错误,如果有就开始执行。首先,执行器打开表后,根据表的引擎定义去使用这个表所提供的引擎接口。具体的执行流程:

  1. 使用引擎接口获取到表的第一行,判断该行是否符合语句的要求。如果符合,就将其保存在结果集中,如果不符合,就跳过该行。
  2. 使用引擎借口获取到下一行,重复判断。
  3. 直到将所有行都遍历结束后,将符合要求的结果集返回给客户端。

至此,一条SQL语句就执行结束。

希望我的学习记录会帮助到一些人,如果有任何问题欢迎留言指正。

发布了62 篇原创文章 · 获赞 28 · 访问量 6054

猜你喜欢

转载自blog.csdn.net/Moo_Lavender/article/details/103604698