一条sql语句在mysql中如何执行(查询+更新)

文章目录

    • 一 MySQL 基础架构
      • 1.1 MySQL 基本架构
      • 1.2 Server 层基本组件介绍
        • 1) 连接器
        • 2) 查询缓存(MySQL 8.0 版本后移除)
        • 3) 分析器
        • 4) 优化器
        • 5) 执行器
    • 二 语句分析
      • 2.1 查询语句
      • 2.2 更新语句
        • 为什么要用两个日志模块,用一个日志模块不行吗?
        • 为什么必须有“两阶段提交”呢?
    • 三 总结

本篇文章会分析一下一个 sql 语句在 MySQL 中的执行流程,包括 sql 的查询在 MySQL 内部会怎么流转,sql 语句的更新是怎么完成的。

在分析之前我会先介绍下 MySQL 的基础架构,知道了 MySQL 由哪些组件组成以及这些组件的作用是什么,可以帮助我们理解和解决这些问题。

一 MySQL 基础架构

1.1 MySQL 基本架构

从下图你可以很清晰的看到用户的 SQL 语句在 MySQL 内部是如何执行的。

先简单介绍一些组件的基本作用帮助大家理解这幅图

  • 连接器: 身份认证和权限相关(登录 MySQL 的时候)。
  • 查询缓存: 执行查询语句的时候,会先查询缓存(MySQL 8.0 版本后移除,因为这个功能不太实用)。
  • 分析器: 没有命中缓存的话,SQL 语句就会经过分析器,分析器说白了就是要先看你的 SQL 语句要干嘛,再检查你的 SQL 语句语法是否正确。
  • 优化器: 按照 MySQL 认为最优的方案去执行。
  • 执行器: 执行语句,然后从存储引擎返回数据。

在这里插入图片描述

简单来说 MySQL 主要分为 Server 层和存储引擎层:

  • Server 层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binlog 日志模块。
  • 存储引擎: 主要负责数据的存储和提取,其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎,其中 InnoDB 引擎有自己的日志模块 redolog 模块。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始就被当做默认存储引擎了。

1.2 Server 层基本组件介绍

1) 连接器

连接器主要和身份认证和权限相关的功能相关,就好比一个级别很高的门卫一样。负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作。

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

2) 查询缓存(MySQL 8.0 版本后移除)

查询缓存主要用来缓存我们所执行的 SELECT 语句以及该语句的结果集。

MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果。

  • 如果你的查询能够直接在这个缓存中找到 key,那么这个value 就会被直接返回给客户端。
  • 如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。你可以看到,如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。

但MySQL 查询不建议使用缓存,因为查询缓存失效在实际业务场景中可能会非常频繁,只要有对一个表的更新,那么这个表上所有的查询缓存都会被清空。对于不经常更新的数据来说,使用缓存还是可以的。

所以,一般在大多数情况下我们都是不推荐去使用查询缓存的。MySQL 8.0 版本后删除了缓存的功能。

3) 分析器

如果没有命中查询缓存,就要开始真正执行语句了。首先,MySQL 需要知道你要做什么。那么就会进入分析器,分析器主要是用来分析 SQL 语句是来干嘛的,分析器也会分为几步:

第一步,词法分析,一条 SQL 语句有多个字符串和空格组成,MySQL 需要识别出里面的字符串分别是什么,代表什么。比如 select,提出查询的表,提出字段名,提出查询条件等等。

例如输入:

select ID from T 

MySQL 从你输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符
串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID

做完这些操作后,就会进入第二步。

第二步,语法分析,根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。

完成这 2 步之后,MySQL 就准备开始执行了,但是如何执行,怎么执行是最好的结果呢?这个时候就需要优化器上场了。

4) 优化器

优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序等。

可以说,经过了优化器之后可以说这个语句具体该如何执行就已经定下来。然后进入执行器阶段。

5) 执行器

MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。

当选择了执行方案后,MySQL 就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。

二 语句分析

2.1 查询语句

通过上面的介绍大家应该对执行一条sql的基本流程已经清楚了,接下来详细介绍一条sql是如何执行的。我们的 sql 可以分为两种,一种是查询,一种是更新(增加,更新,删除)。我们先分析下查询语句,语句如下:

select * from sys_student  A where A.age=18 and A.name='Bruce';

结合上面的说明,我们分析下这个语句的执行流程:

  • 连接器登录认证通过后,先检查该用户是否有权限,如果没有权限,直接返回错误信息,如果有权限,在 MySQL8.0 版本以前,会先查询缓存,以这条 sql 语句为 key 在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。

  • 通过分析器进行词法分析,提取 sql 语句的关键元素,比如提取上面这个语句是 select 查询操作,提取需要查询的表名为 sys_student ,需要查询所有的列,查询条件是这个表的 age=‘18’ and name=‘Bruce’。然后进行语法分析,判断这个 sql 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。

  • 接下来就是优化器进行确定执行方案,上面的 sql 语句,可以有两种执行方案:

      a.先查询学生表中姓名为“Bruce”的学生,然后判断是否年龄是 18。
      b.先找出学生中年龄 18 岁的学生,然后再查询姓名为“Bruce”的学生。
    

    那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。

  • MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。开始执行前先进行权限校验,如果没有权限就会返回错误信息,如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口,返回引擎的执行结果。

2.2 更新语句

以上就是一条查询 sql 的执行流程,那么接下来我们看看一条更新语句如何执行的呢?sql 语句如下:

update sys_student  A set A.age=19 where A.name=' Bruce ';

我们来给Bruce修改下年龄,这条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,MySQL 自带的日志模块是 binlog(归档日志) ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 redo log(重做日志),我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下:

  • 先查询到name=Bruce这一条或多条数据,。如果name=Bruce 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
  • 然后拿查询得到的语句,把 age 改为 19,然后调用引擎 API 接口,写入这一行数据,InnoDB 引擎把数据保存在内存中,同时记录 redo log,此时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,随时可以提交。
  • 执行器收到通知后,记录 binlog,然后调用引擎接口,提交 redo log 为提交状态。
  • 更新完成。

为什么要用两个日志模块,用一个日志模块不行吗?

因为最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是
MyISAM 没有 crash-safe 的能力(crash-safe 的能力:即使数据库发生异常重启,之前提交的记录都不会丢失)。,binlog 日志只能用于归档(用于记录数据库执行的写入性操作信息,记载的是update/delete/insert这样的SQL语句,数据的逻辑变化)。而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB使用另外一套日志系统——也就是 redo log 来实现 crash-safe 能力(redo log记载的是物理修改的内容:xxxx页修改了xxx。redo log的作用是为持久化而生的。写完内存,如果数据库挂了,那我们可以通过redo log来恢复内存还没来得及刷到磁盘的数据,将redo log加载到内存里边,那内存就能恢复到挂掉之前的数据了。)

并不是说只用一个日志模块不可以,只是 InnoDB 引擎就是通过 redo log 来支持事务的。

为什么必须有“两阶段提交”呢?

这是为了让两份日志之间的逻辑一致。

  • 先写 redo log 直接提交,然后写 binlog,假设写完 redo log 后,binlog还没写完,MySQL 进程异常重启。由于我们前面说过的,redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所有恢复后,这一行age的值是19。
    但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。同时主从同步也会丢失这一条数据。
  • 先写 binlog,然后写 redo log,假设写完了 binlog,MySQL 进程异常重启了,由于没有 redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。

如果采用 redo log 两阶段提交的方式就不一样了,当写入redo log 处于prepare状态,binlog 也已经写完了,这个时候发生了异常重启MySQL 的处理过程如下:

  • 如果redo log处于commit状态,则判断 redo log 是否完整,如果判断是完整的,就立即提交。
  • 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果binlog完整就提交 redo log, 不完整就回滚事务。

这样就解决了数据一致性的问题。

三 总结

  • MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存(MySQL 8.0 版本后移除)、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用,redolog 只有 InnoDB 有。
  • 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory 等。
  • 查询语句的执行流程如下:连接数据库----》权限校验—》查询缓存—》分析器—》优化器—》权限校验—》执行器—》引擎
  • 更新语句执行流程如下:连接数据库----》权限校验—》分析器----》优化器----》权限校验----》执行器—》引擎—》写入redo log(prepare 状态)—》写binlog—》提交事务,redo log处于commit状态

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

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

相关文章

初识Java集合框架

前言 在大多数情况下,你常常会看到《C数据结构》类似的书籍,很多人可能会认为数据结构是一门依赖语言的学科,有了语言才可能有数据结构,其实这里需要纠正的是, 数据结构(Data Structure)是计算机存储、组织数据的方式…

Ubuntu类IOS主题设置

1.依次执行下面三条命令&#xff1a; sudo apt install gnome-shell-extensions sudo apt install gnome-tweak-tool sudo apt install chrome-gnome-shell2.下载主题&#xff0c;也是命令&#xff1a; git clone <https://github.com/qingchendelaike/GNOME-OSX-II-Theme…

Unity之获取用户地理位置

1.直接利用三方API获取&#xff1a; 1.1 利用bilibili的api 【未知稳定性】 public void Awake() {StartCoroutine(GetLocationInfoNew());}/// <summary>/// 利用bilibili的接口通过ip直接获取城市信息/// </summary>IEnumerator GetLocationInfoNew() {//UnityW…

python优雅地爬虫

申明&#xff1a;仅用作学习用途&#xff0c;不提供任何的商业价值。 背景 我需要获得新闻&#xff0c;然后tts&#xff0c;在每天上班的路上可以听一下。具体的方案后期我也会做一次分享。先看我喜欢的万能的老路&#xff1a;获得html内容-> python的工具库解析&#xff0…

Linux常见命令

新建标签页 (gitee.com)尹相辉 (yinxianghui66) - Gitee.com新建标签页 (gitee.com) 文章目录 文章目录 一、Linux常见命令 1.ls 2.cd 目录名 3.pwd 4.touch 文件名 5.echo 字符串->目标文件 6.cat 文件名 7.man 8.vim 文件名 9.mkdir 目录名 10.rm 文件名 11.mv 源…

【贪心算法】leetcode刷题

贪心算法无固定套路。 核心思想&#xff1a;先找局部最优&#xff0c;再扩展到全局最优。 455.分发饼干 两种思路&#xff1a; 1、从大到小。局部最优就是大饼干喂给胃口大的&#xff0c;充分利用饼干尺寸喂饱一个&#xff0c;全局最优就是喂饱尽可能多的小孩。先遍历的胃口&a…

zadig安装驱动潜在风险与解决策略

zadig安装驱动潜在风险与解决策略 ✨没事不要闲着乱打驱动&#xff0c;能正常使用的情况下&#xff0c;不要轻易或随意去乱打驱动&#xff0c;可能会导致新的驱动对已有的设备不兼容的问题。✨&#x1f530;特别说明&#xff1a;本文介绍的方法&#xff0c;并不能包治百病&…

【MATLAB第67期】# 源码分享 | 基于MATLAB的morris全局敏感性分析

【MATLAB第67期】# 源码分享 | 基于MATLAB的morris全局敏感性分析 一、代码展示 clear all npoint100;%在分位数超空间中要采样的点数(计算次数iternpoint*(nfac1) nfac20;%研究函数的不确定因素数量 [mu, order] morris_sa1((x)test_function(x), nfac, npoint)for t1:size…

vite跨域配置踩坑,postman链接后端接口正常,但是前端就是不能正常访问

问题一&#xff1a;怎么都链接不了后端地址 根据以下配置&#xff0c;发现怎么都链接不了后端地址&#xff0c;proxy对了呀。 仔细看&#xff0c;才发现host有问题 // 本地运行配置&#xff0c;及反向代理配置server: {host: 0,0,0,0,port: 80,// cors: true, // 默认启用并允…

vscode 搭建STM32开发环境

1.需要软件 1.1 vscode 1.2 STM32CubeMX&#xff0c;这个不是必须的&#xff0c;我是为了方便生成STM32代码 2.vscode配置 2.1安装keil Assistant 2.2配置keil Assistant 3.STMCUBE生成个STM32代码 &#xff0c;如果有自己的代码可以忽略 4.代码添加到vscode&#xff0c;并…

iPhone手机怎么恢复出厂设置(详解)

如果您的iPhone遇到了手机卡顿、软件崩溃、内存不足或者忘记手机解锁密码等问题&#xff0c;恢复出厂设置似乎是万能的解决方法。 什么是恢复出厂设置&#xff1f;简单来说&#xff0c;就是让手机重新变成一张白纸&#xff0c;将手机所有数据都进行格式化&#xff0c;只保留原…

无货源跨境电商购物平台快速搭建(微商城、小程序、APP、网站)

无货源跨境电商购物平台的快速搭建可以通过以下步骤完成&#xff0c;并且可以同时开发微商城、小程序、APP和网站以满足不同用户的需求。 第一步&#xff1a;需求分析 在搭建之前&#xff0c;需要对平台的需求进行详细的分析。包括用户需求、功能需求、技术需求等等。这一步是…

北航基于openEuler构建工业机器人操作系统,打造“开箱即用”的机器人基础软件平台

北京航空航天大学是国家“双一流”建设高校&#xff0c;以建设扎根中国大地的世界一流大学为发展目标。北京航空航天大学在机器人领域一直处于行业前沿&#xff0c;以其亮眼的成果和优秀的师资力量&#xff0c;成为国内机器人领域的重要参与者和建设者。机器人操作系统是机器人…

浅谈什么是 Spring Cloud,快速学习与使用案例(文末送书福利3.0)

文章目录 &#x1f4cb;前言&#x1f3af;什么是 Spring Cloud&#x1f3af;快速入门 Spring Cloud&#x1f9e9;使用 Eureka 进行服务注册和发现 &#x1f4dd;最后&#x1f3af;文末送书&#x1f4da;内容介绍&#x1f4da;作者介绍 &#x1f525;参与方式 &#x1f4cb;前言…

erp与crm的区别有哪些呢?两者之间有什么联系?

阅读本文您可以了解&#xff1a;1、crm系统的功能&#xff1b;2、erp系统的功能&#xff1b;3、crm系统和erp系统的区别 一、crm系统是什么 CRM系统是客户关系管理系统的缩写。它是一种用于帮助企业有效管理与客户关系相关的信息、活动和数据的软件工具或平台。 举个例子&…

【ArcGIS】经纬度数据转化成平面坐标数据

将点位置导入Gis中&#xff0c;如下&#xff08;经纬度表征位置&#xff09;&#xff1a; 如何利用Gis将其转化为平面坐标呢&#xff1f; Step1 坐标变换 坐标变换&#xff0c;打开ArcToolbox&#xff0c;找到“数据管理工具”->“投影和变换”->“要素”->“投影”…

Fastjson 使用指南

文章目录 Fastjson 使用指南0 简要说明为什么要用JSON&#xff1f;用JSON的好处是什么&#xff1f;为什么要用JSON&#xff1f;JSON好处 1 常用数据类型的JSON格式值的范围 2 快速上手2.1 依赖2.2 实体类2.3 测试类 3 常见用法3.1 序列化操作核心操作对象转换为JSON串list转换J…

[C++]类与对象(下) -- 初始化列表 -- static成员 -- 友元 -- 内部类,一篇带你深度了解。

目录 1、再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.2.1 初始化列表的意义 1.3 explicit关键字 2、static成员 2.1 问题引入 2.2 特性 3、友元 3.1 友元函数 3.2 友元类 4、内部类 1、再谈构造函数 1.1 构造函数体赋值 在创建对象时&#xff0c;编译器通…

nginx(八十六)uri转义杂谈

一 关于nginx uri过往整理 HTTP1.1(四)URI HTTP1.1(五)URI编码 HTTP杂谈(三)URL特殊字符 以下涉及&#xff1a; 1) location 与$uri --> 路由匹配 --> 通过debug日志观察2) proxy_paas --> attach_url是否有,有是否是变量,决定透传给上游uri的形式3) $reque…

软件编程专业:探索计算机世界的奥秘

软件编程专业&#xff1a;探索计算机世界的奥秘 随着科技的飞速发展&#xff0c;计算机已经渗透到我们生活的方方面面。我们每天都在使用各种应用程序&#xff0c;比如社交媒体、游戏和电子邮件等&#xff0c;而这些应用程序背后的魔法都是由软件编程专业的人创造的。那么&…