Mysql(一)查询Sql是如何执行的

Hello,大家好我是极客涛😎,我最近在整理Mysql相关的知识点,所以准备开启一个Mysql的主线任务,大概耗时3周左右,整个节奏还是由浅入深,主要包括Mysql的架构、事务实现、索引组织形式、SQL优化、日志系统、锁、主从架构、无锁变更、最佳实践等等。大家可以随着我的这个路线,一起沉淀沉淀,如何检验自己的学习成果呢,刷面试题,遇到不清楚的在往深里研究。好了,那我们开始~

引言

我们知道Mysql是一个数据库系统,提供了对数据的增删改查API,我们通过一条条简单的SQL就可以实现对系统的各种操作,为了更容易理解,我们按照从整体到局部的思路,先鸟瞰Mysql整体的架构,然后再对每个细节深入研究,所以今天我们通过一条查询SQL的执行流程,看一看Mysql的应用架构是如何组成的。

本文结构
请添加图片描述

阅读体验

📚 全文字数 : 4k+
⏳ 阅读时长 : 6min

Mysql的应用架构

Mysql的应用架构遵循了职责单一、能力分层、插件化的原则。整体上看,Mysql主要分为服务层和引擎层:

服务层:Mysql的通用能力层,负责对外(客户端)暴露端口、解析SQL语法、执行SQL优化、通过调用引擎层的API对整个查询过程进行API调用的编排。

引擎层:引擎层负责对数据的存储和读取,并通过API将能力暴露给服务层使用。Mysql支持不同的存储引擎通过插件的方式接入Mysql的服务层,不同的存储引擎适用于不同的使用场景,如Memory、InnoDB、MySAM。

再进行细分的话,服务层又包括:连接器、查询缓存、分析器、优化器、执行器。
请添加图片描述

连接器

不管Mysql内部如何运行,都需要有一个与外界进行交互的桥梁,连接器就起到了桥梁的作用。连接器是Mysql的统一门面,负责与客户端建立会话连接、进行用户认证、查询用户权限、维持和管理会话连接。

mysql -h$ip -P$oprt -u$username -p$password

当我们执行mysql的连接命令时,通过ip + port 定位到是哪个Mysql服务,经过TCP握手之后,连接器和客户端就建立了会话连接,然后这条命令就来了连接器。连接器首先通过 -u-p 参数对本次请求进行认证操作,验证用户是否在Mysql服务中注册过,密码是否正确,如果认证失败,则直接响应Access denied for user ‘xxx’@‘localhost’ (using password: YES)

认证通过后,连接器则会查询用户的权限列表,判断对该用户是否开放了远程连接权限。Mysql默认只允许本机(localhost)进行连接操作,如果没有远程连接权限直接响应Access denied for user ‘root’@‘%’ to database ‘mysql。如果有远程连接权限,那么本次连接就真正意义上建立完成了。需要注意的是,查询出来的权限列表会一直向下传递,之后对表的权限校验、对操作的权限校验都依赖于这个权限列表。

正是因为先鉴权再建立会话连接,所以即使对当前连接用户的权限进行了修改,也不会立即生效,需要等到下次重新连接时才会生效。

为了提高资源的利用率,当客户端与连接器建立连接之后,如果客户端长时间没有进行任何操作,连接器会自动将这个连接断开(默认是8小时,由wait_timeout参数控制)。

在客户端与服务端的通信中,一般分为长连接短连接长连接就是客户端和服务端建立连接之后会一直保持的这个连接,后续的任意操作不会重建连接,这样避免了每次操作需要重新创建连接的操作,执行速度会快很多。但是连接不释放就意味着对象不能销毁,如果连接数过多的话,可能会导致Mysql服务因内存不足而重启;短连接相反,每次请求都需要重新创建连接,相对来说执行速度会慢一些,但是每次请求完都释放连接和对象,这样消耗的内存资源要大大降低。

从客户端的角度来说,肯定更中意使用长连接,因为可以提高响应速度;从服务端的角度来说,更中意短连接,因为逻辑简单,资源消耗少。那如何中和两个方案的优缺点呢?连接池就顺势而生了,连接池是存在于客户端的,应用程序会在初始化时通过连接池申请若干个长连接,而应用程序内的所有线程共享这个连接池,因为一次请求很快就结束了,这样其它请求来的时候可以复用这个连接,而当某个连接长时间没有被使用时,就将其释放,这样便发挥了长连接和短连接各自的优点。

查询缓存

select * from geektao where id = 2;

通过连接器的认证鉴权之后,就开始进行查询操作了。

首先会看看当前SQL是否已经在查询缓存中存在,查询缓存通过key=value的方式存储SQL及其执行结果,如果存在则直接返回缓存中的执行结果,查询效率大大提高。

但是在实际的生产使用过程中并不建议使用查询缓存,因为生产中被查询的数据往往是不断变化的,这样就会造成缓存一直失效,每次查询完之后还要设置缓存,不仅没有提高查询效率,反而造成额外的开销,使用起来很鸡肋。Mysql8.0版本直接把查询缓存整个模块删掉了,如果版本小于8.0的话可以通过设置query_cache_type=DEMAND关闭查询缓存。

分析器

如果查询缓存关闭或者缓存中没有的话,那么就真真正正的开始解析SQL了。了解编译原理的同学应该知道,作为一个解析器不可缺少的三个功能:词法分析语法分析语义分析

词法分析

词法分析是SQL解析的第一步,它负责将输入的SQL语句字符串分解成一系列的Token(词元)。这些Token是SQL语法的基本组成单元,例如关键字(如SELECTFROM等)、标识符(如表名、列名)、常量值等。但是此时分析器还不知道什么意思,就像我们小时候学字一样,只知道王是王,李是李,并不理解。

语法分析

语法分析阶段,MySQL根据SQL语言的语法规则,将词法分析阶段产生的Token序列转换成一个抽象语法树(Abstract Syntax Tree,AST)。这个过程中,会检查SQL语句是否符合MySQL的语法规则。这时候就像小时候已经开始学造句了,根据特定的语法造句,但是也没有真正理解造出来句子的含义。

语义分析

在语法分析之后,接下来就是语义分析阶段。在这个阶段,MySQL的解析器会检查抽象语法树是否有意义,即检查SQL语句在逻辑上是否正确。这包括识别列名、检查数据类型、确定操作符函数的正确使用、处理别名表达式等。如果在这个阶段发现错误,比如找不到表或列、类型不匹配等,解析器会生成错误信息,此时Mysql才真正理解了这条SQL到底想干啥了。

优化器

经过分析器之后,Mysql就知道我们想干什么了,那下一步是不是就直接去干了。Mysql可没有你想的这么简单,在去干前,Mysql会”思考“如何使用最的查询步骤来查询。

优化器会根据抽象语法树生成执行计划,如果表中有多个索引的话会确定去哪个索引里查询,如果是多表关联查询的话会确定先去哪个表查询再去哪个表查询。总之,优化器会根据不同的情况制定出一个最优的方案,这样Mysql才知道怎么做。

执行器

对执行器来说”器如其名“,前边我们已经通过分析器知道了要做什么通过优化器知道了怎么做而执行器通过执行计划一步步的执行

在执行之前,执行器首先会判断当前用户是否对表有相关的操作权限,而判断的依据就是连接器当时查询出来的权限列表。有同学可能有疑问,到执行器在进行表的权限校验是不是有些晚了,在分析器阶段不是已经知道是要操作哪张表了吗?

确实,在优化器之前会调用precheck验证权限,但是这时候只是进行简单的权限校验,查询的表存不存在、列存不存在,对查询的表有没有操作权限,这些校验都是静态校验。在真正执行时也需要动态校验,因为执行时是运行态,比如该表有个触发器,只能在执行阶段才能进行校验(有一点点像class文件加载过程中的验证阶段)。

执行器阶段的权限校验通过之后,就开始调用执行引擎的接口进行数据读取操作了。

假设不走索引的情况

  1. 打开要查询的表;

  2. 调用执行引擎接口获取第一行记录,判断id是否等于2,等于则保存结果到结果集中;

  3. 调用执行引擎接口获取下一行记录,判断id是否等于2,等于则保存结果到结果集中;

  4. …;

  5. 没有下一行数据,调用结束;

  6. 执行器将结果集返回给客户端。

至此,一条查询语句便执行完毕。

小结

今天主要讲解了Mysql的应用架构,并通过查询SQL为例,对Mysql的每个组件及其作用都进行了描述,相信大家对Mysql整个运行流程有了一个大概的了解,下边给大家留了一些问题加深大家的印象😄。

问题

  1. Mysql的基本架构包括什么,每部分有哪些作用?
  2. select * from geektao where name = 'xx';当表中没有name字段时会怎么样?这是在哪一步判断的?
  3. 为什么要使用连接池?工作原理是什么?一般如何进行参数调优?
  4. 如果Mysql服务端因升配导致连接失效,客户端该如何自动重连?
  5. Mysql哪些阶段会进行权限校验,目的是什么?
  6. select sum(amount) from geektao;sum()是在哪一步计算的?
  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值