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()是在哪一步计算的?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/668576.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kettle 使用动态变量名定义变量

name是变量,value 值也是变量 我需要把name作为变量名,value作为变量值; 在kettle中,使用javascript脚本 key与lastVsxzl都是变量 //Script here setVariable(key,lastVsxzl,r);var rgetVariable(key,r); Demo 1、从记事本里面…

sensitive-word 敏感词 v0.16.1 新特性支持字典内存资源释放

敏感词系列 sensitive-word-admin 敏感词控台 v1.2.0 版本开源 sensitive-word-admin v1.3.0 发布 如何支持分布式部署? 01-开源敏感词工具入门使用 02-如何实现一个敏感词工具?违禁词实现思路梳理 03-敏感词之 StopWord 停止词优化与特殊符号 04-…

【第十三节】C++控制台版本坦克大战小游戏

目录 一、游戏简介 1.1 游戏概述 1.2 知识点应用 1.3 实现功能 1.4 开发环境 二、项目设计 2.1 类的设计 2.2 各类功能 三、程序运行截图 3.1 游戏主菜单 3.2 游戏进行中 3.3 双人作战 3.4 编辑地图 一、游戏简介 1.1 游戏概述 本项目是一款基于C语言开发的控制台…

linux--------线程的同步和互斥

前言 提示:以下是本篇文章正文内容,下面案例可供参考 一、线程互斥 (1)互斥: 任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用 要了解互…

fastjson 泛型转换问题(详解)

系列文章目录 附属文章一:fastjson TypeReference 泛型类型(详解) 文章目录 系列文章目录前言一、代码演示1. 不存在泛型转换2. 存在泛型转换3. 存在泛型集合转换 二、原因分析三、解决方案1. 方案1:重新执行泛型的 json 转换2. …

使用Python突破网站验证码限制

之前有小伙伴说,在web自动化的过程中,经常会被登录的验证码给卡住,不知道如何去通过验证码的验证,今天专门给大家来聊聊验证码的问题。 常见的验证码一般分为两类,一类是图文验证码,一类是滑块验证码&#…

c#基础()

学习目标 了解:嵌套类,匿名类,对象初始化器 重点:类的定义以及对象,构造方法,this和static关键字 掌握:面向对象的概念,访问修饰符,垃圾回收 面向对象 面向对象的概…

面试题:SpringBoot启动流程

具体步骤 新建一个Spring应用程序 (new springApplication()): 确认web应用的类型加载ApplicationContextInitializer加载ApplicationListener记录主启动类 运行应用程序(.run): 准备环境对象Environment,用于加载…

Java学习【String类详解】

Java学习【String类详解】 String的介绍及定义方式String类型的比较String类型的查找charAt()访问字符indexOf()查找下标 转化和替换数值和字符串转化大小写的转换字符串转数组格式化替换 字符串的拆分和截取split()拆分substring()截取trim()去除两边空格 StringBuilder和Stri…

09Linux GDB学习笔记

Linux GDB使用 目录 文章目录 Linux GDB使用先编译文件1.检查安装1.1 安装GDB 2.启动GDB3.退出GDB4.设置断点4.1 在指定行号处设置断点4.2 在指定函数名处设置断点4.3 在指定源文件和行号处设置断点 4.4查看断点信息4.5删除断点5.运行5.1 <font color#ff0000>逐过程&am…

java web爬虫

目录 读取本地文件 从网站读取文件 java爬虫 总结 读取本地文件 import java.io.File; import java.io.PrintWriter; import java.util.Scanner;public class ReplaceText {public static void main() throws Exception{File file new File("basic\\test.txt"…

Sui与Atoma合作为开发者提供AI支持

AI初创公司Atoma宣布其即将推出的推理网络将与Sui集成&#xff0c;该网络将使开发者能够在他们的应用程序中使用AI工具。Atoma选择Sui作为其第一个区块链集成对象是由于Sui的可扩展性和性能。 尽管生成式AI在过去几年中引起了轰动&#xff0c;但它尚未进入许多消费者应用程序。…

openfiler安装部署-1

openfiler安装部署 简介1 下载openfiler2 openfiler 安装2.1 vmware 典型配置2.2 稍后安装操作系统2.3 新建虚拟机向导2.4 命名虚拟机2.5 指定磁盘容量2.6 添加系统镜像&#xff0c;准备安装系统2.7 启动安装系统2.8 初始化磁盘&#xff0c;选择"Yes"2.9 创建分区&am…

软链接和硬链接

1.软链接 > 也称为符号链接 1.1软链接的创建 注&#xff1a;不管是源文件还是链接文件&#xff0c;最好都用上绝对路径 ln -s 链接源 链接名 //创建链接文件 ln -sf 链接源 链接名 //修改链接的源 s 如果目标链接名称已经存在&#xff0…

C语言数据结构排序、插入排序、希尔排序等的介绍

文章目录 前言打印数组函数一、插入排序二、希尔排序总结 前言 C语言数据结构排序、插入排序、希尔排序等的介绍 打印数组函数 打印数组函数定义 // 打印数组 void PrintArray(int* a, int n) {int i 0;for (i 0; i < n; i){printf("%d ", a[i]);}printf(&qu…

Vivado 比特流编译时间获取以及FPGA电压温度获取(实用)

Vivado 比特流编译时间获取以及FPGA电压温度获取 语言 &#xff1a;Verilg HDL 、VHDL EDA工具&#xff1a;ISE、Vivado Vivado 比特流编译时间获取以及FPGA电压温度获取一、引言二、 获取FPGA 当前程序的编译时间verilog中直接调用下面源语2. FPGA电压温度获取&#xff08;1&a…

大厂Java面试题:MyBatis的映射器(Mapper.xml)中有哪些常见的元素?

大家好&#xff0c;我是王有志。今天给大家带来的是一道来自京东的 MyBatis 面试题&#xff1a;MyBatis的映射器&#xff08;Mapper.xml&#xff09;中有哪些常见的元素&#xff1f;MyBatis 的映射器中提供了 9 个顶级元素&#xff0c;按照功能可以分为 3 类&#xff1a; SQL …

常用电机测试方法的介绍与功能实现(M测试方法)

目录 概述 1 常用电机测速方法简介 1.1 方法概览 1.2 编码器测速方法 2 M法测速 2.1 理论描述 2.2 实现原理 2.3 速度计算方法 3 功能实现 3.1 功能介绍 3.2 代码实现 3.2.1 使用STM32Cube配置参数 3.2.2 脉冲计数功能 3.2.3 测速函数 4 测试 概述 本文主要介绍…

MySQL:CRUD进阶(七千五百字)

文章目录 前置文章&#xff1a;&#x1f4d1;1. 数据库约束&#x1f324;️1.1 约束类型&#x1f324;️1.2 NULL约束&#x1f324;️1.3 Unique&#xff1a;唯一约束&#x1f324;️1.4 Default&#xff1a;默认值约束&#x1f324;️1.5 Primary key&#xff1a;主键约束&…

一个不错的讲解做竞品分析的方法

比如选了竞品1&#xff0c;竞品2&#xff0c;然后每个功能项&#xff0c;选定1个做标准被比较的锚点&#xff0c;比如外观&#xff0c;用竞品2&#xff0c;设置为1分&#xff0c;然后看竞品1&#xff0c;在外观的评分上&#xff0c;相比竞品2&#xff0c;是分数低点还是高点&am…