【MySQL | 第十一篇】一条SQL语句在MySQL的执行过程

在这里插入图片描述

文章目录

  • 11.一条SQL语句在MySQL的执行过程
    • 11.1MySQL整体架构
    • 11.2SQL语句在Server层执行流程
    • 11.3拓展:InnoDB存储引擎的更新操作
      • 11.3.1问题:为什么写了redolog日志还要写binlog日志?
      • 11.3.2问题:为什么要两阶段提交?
      • 11.3.3流程小结(8步,非常重要)
    • 11.4查询优化小结

11.一条SQL语句在MySQL的执行过程

11.1MySQL整体架构

image-20240502163558086

MySQL 逻辑架构图主要分三层:

  • 客户端:最上层的服务并不是 MySQL 所独有的,大多数基于网络的客户端/服务器的工具或者服务都有类似的架构。比如连接处理、授权认证、安全等等
  • Server 层:大多数 MySQL 的核心服务功能都在这一层,包括查询解析、分析、优化、缓存(MySQL8版本后移除)以及所有的内置函数(例如,日期、时间、数学和加密函数),所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。
  • 存储引擎层:第三层包含了存储引擎。存储引擎负责 MySQL 中数据的存储和提取。Server 层通过 API 与存储引擎进行通信。这些接口屏蔽了不同存储引擎之间的差异,使得这些差异对上层的查询过程透明。

11.2SQL语句在Server层执行流程

  • 下面我们分析一下一条查询语句的执行流程
select user_id、username 
from t_user 
where username = "张三" and sex = 1
  1. 客户端发起查询请求,与连接器建立连接,连接器确定用户是否有查询权限,没有权限,直接返回错误信息,有执行下一步。

  2. 查询缓存(MySQL8.0 以前),以这条SQL语句为key在内存缓冲池中是否有结果,有直接返回结果,无则执行下一步。

  3. 分析器进行词法分析,提取出操作为select, 表名为 t_user, 查询字段为user_id、username,查询条件为username=“张三” 和 sex=1 ,把提取的Token转换为抽象语法树.如下图

在这里插入图片描述

接下来分析器分析这个 sql 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。

  1. 优化器列出可能的执行方案

  2. 先查询t_user表中username=“张三”的学生,然后判断是否性别为男。

  3. 先找出学生中性别是男的学生,然后再查询username为“张三”的学生。

  4. 接下来计算两个查询计划的成本,若username字段为索引,usrname和sex为联合索引、或查询条件可能致使索引失效,查询字段为*,造成成全表扫描,都有可能影响执行方案的选择。

  5. 执行器进行权限校验,如果没有权限就会返回错误信息,如果有权限就执行器会调用数据库引擎接口,返回引擎的执行结果

  6. 执行引擎根据执行计划查询数据,并把结果集返回客户端

  • 总结SQL语句执行流程:权限校验—》查询缓存—》分析器—》优化器—》权限校验—》执行器—》引擎

11.3拓展:InnoDB存储引擎的更新操作

上面介绍的是查询语句执行流程,而一条更新语句的的查询过程基本是沿用上面的步骤,但在更新的时候要记录日志。下面我们来探索一下在InnoDB存储引擎是如何保证更新语句的成功执行。以下面语句为例(user_id=1这条记录原始值为“张三”)。

update t_user set username = "李四" where user_id = 1
  1. InnoDB会先去BufferPool中去查找user_id=1的数据,没找到就会去磁盘中查找,如果查找到就会将这条记录加载到缓冲池BufferPool中,由于是更新操作,InnoDB会对这条记录加锁。

  2. 我们都知道SQL语句执行前默认是开启事务的,考虑到更新失败后的数据回滚,把更新前的数据写入undolog中

  3. 更新缓存池BufferPool的值为“李四”

    在这里插入图片描述

  4. 此时内存中的数据已经修改,但磁盘中的数据还未更新,为避免数据的丢失,需要把更新的值写入redo log Buffer中,

  5. 此时就可以准备事务的提交了,提交事务的同时会根据一定策略把redo log从buffer中刷入磁盘。此时若MySQL崩溃,重启可根据redo log日志把数据重新写入BufferPool中,避免了数据的丢失。此时redo log 处于 prepare 状态

可通过innodb_flush_log_at_trx_commit 参数来设置redo log刷盘策略。值为 0 表示不刷入磁盘; 值为 1 表示立即刷入磁盘 ;值为 2 表示先刷到 os cache

在这里插入图片描述

  1. 到这里InnoDB层面的操作就差不多了,接下来执行器会生成更新操作的 binlog,并把binlog 日志写入磁盘
  2. 把本次更新的binlog文件名称和本次更新的binlog日志在文件里面的位置,都写入到redo日志文件中,同时在redo log日志中打上一个commit标记。此时redo log 处于 commit 状态。至此,事务提交成功
  3. 事务提交成功后,后台会另起io线程把脏数据刷入磁盘中。

在这里插入图片描述

11.3.1问题:为什么写了redolog日志还要写binlog日志?

​ 性质不同

  • redolog是InnoDB独有的,文件大小有限,主要用于崩溃恢复
  • binlog是MySQL层面的日志,通过追加的方式记录,主要用于主从复制和数据恢复

11.3.2问题:为什么要两阶段提交?

我们看到redolog的提交分为两阶段,prepare和commit。为什么不先写binlog呢?

  • 原因:
    • 第5步和第6步都是事务开始的时候,一旦任意一步执行完毕因为系统宕机了。只写了两个中的任意一个。此时就会导致redo和binlog日志不一致的情况。
    • 并且即使执行了5,6步成功了,也不能保证redo和binlog日志是一样的。这就会导致了数据不一致的问题。而commit就是保证连个日志数据一致,事务才算提交成功

11.3.3流程小结(8步,非常重要)

  1. BufferPool查找数据
  2. 原来的数据写入undo log
  3. 修改BufferPool数据
  4. 写入redo log buffer
  5. 提交事务时,把redo log刷盘(prepare状态)
  6. 执行器会生成更新操作的 binlog,binlog 刷盘
  7. redo log(打上commit标记)
  8. 内存中脏数据刷入磁盘

11.4查询优化小结

1、查询的时候用什么字段查什么字段,

2、避免索引失效(如子查询、!=、like 以%开头,复合索引不在第一列索引、使用函数)

在这里插入图片描述

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

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

相关文章

《QT实用小工具·四十七》可交互的创意动态按钮

1、概述 源码放在文章末尾 该项目实现了可交互的创意动态按钮,包含如下功能: 所有颜色自定义 鼠标悬浮渐变 两种点击效果:鼠标点击渐变 / 水波纹动画(可多层波纹叠加) 额外鼠标移入/移出/按下/弹起的实时/延迟共8种事…

springboot 自动配置源码解读

什么是自动装配 当我们程序依赖第三方功能组件时,不需要手动将这些组件类加载到IOC容器中。例如 当程序需要用到redis时,在pom.xml文件中引入依赖,然后使用依赖注入的方式直接从IOC容器中拿到相应RedisTemplate实例。 SpringBootApplication …

【已解决】json文件太大无法打开怎么办+ijson报错

下载了一个json文档,尝试了全部的编辑器都打不开。。。 搜了搜或许可以使用ijson GitHub - ICRAR/ijson: Iterative JSON parser with Pythonic interfaces "Ijson is an iterative JSON parser with standard Python iterator interfaces." 示例代码&…

【C++ —— 多态】

C —— 多态 多态的概念多态的定义和实现多态的构成条件虚函数虚函数的重写虚函数重写的两个例外协变:析构函数的重写 C11 override和final重载、覆盖(重写)、隐藏(重定义)的对比 抽象类概念接口继承和实现继承 多态的继承虚函数表多态的原理动态绑定和静态绑定 单继…

VTK 的可视化方法:Glyph

VTK 的可视化方法:Glyph VTK 的可视化方法:Glyph标量、向量、张量将多边形数据的采集点法向量标记成锥形符号参考 VTK 的可视化方法:Glyph 模型的法向量数据是向量数据,因此法向量不能像前面讲到的通过颜色映射来显示。但是可以通…

25 JavaScript学习:var let const

JavaScript全局变量 JavaScript中全局变量存在多种情况和定义方式,下面详细解释并提供相应的举例: 使用var关键字声明的全局变量: var globalVar "我是全局变量";未使用var关键字声明的变量会成为全局变量(不推荐使用&…

【前端】-【防止接口重复请求】

文章目录 需求实现方案方案一方案二方案三 需求 对整个的项目都做一下接口防止重复请求的处理 实现方案 方案一 思路:通过使用axios拦截器,在请求拦截器中开启全屏Loading,然后在响应拦截器中将Loading关闭。 代码: 问题&…

(刷题记录2)随机链表的复制

[刷题记录2]随机链表的复制 题目信息:题目思路(环境来自力扣OJ的C语言):复杂度:代码和解释:1.遍历一遍原链表的同时,在每个原节点后面插入一个相同的新节点,共插入 n 个新节点。2.利用两者联系,…

神奇的Vue3 - 组件探索

神奇的Vue3 第一章 神奇的Vue3—基础篇 第二章 神奇的Vue3—Pinia 文章目录 神奇的Vue3了解组件一、注册组件1. 全局注册​2. 局部注册3. 组件命名 二、属性详解1. Props(1)基础使用方法(2)数据流向:单项绑定原则&…

ThreeJS:Mesh网格与三维变换

Mesh网格 ThreeJS中,Mesh表示基于以三角形为多边形网格(polygon mesh)的物体的类,同时也作为其它类的基类。 通过Mesh网格,我们可以组合Geometry几何体与Material材质属性,在3D世界中,定义一个物体。例如:之…

vue2(4)之scoped解决样式冲突/组件通信/非父子通信/ref和$refs/异步更新/.sync/事件总线/provide和inject

vue2 一、学习目标1.组件的三大组成部分(结构/样式/逻辑)2.组件通信3.综合案例:小黑记事本(组件版)4.进阶语法 二、scoped解决样式冲突**1.默认情况**:2.代码演示3.scoped原理4.总结 三、data必须是一个函数…

Copilot Venture Studio創始合伙人楊林苑確認出席“邊緣智能2024 - AI開發者峰會”

隨著AI技術的迅猛發展,全球正逐步進入邊緣計算智能化與分布式AI深度融合的新時代,共同書寫著分布式智能創新應用的壯麗篇章。邊緣智能,作為融合邊緣計算和智能技術的新興領域,正逐漸成為推動AI發展的關鍵力量。借助分布式和去中心…

由于找不到mfc140u.dll,无法继续执行的多种解决方法

在我们日常与计算机的密切互动中,或许不少用户都曾遇到过这样一个棘手的问题:系统突然弹出一个提示窗口,告知我们“找不到mfc140u.dll文件”。这个文件是Microsoft Foundation Class(MFC)库的一部分,用于支…

提升编码技能:学习如何使用 C# 和 Fizzler 获取特价机票

引言 五一假期作为中国的传统节日,也是旅游热门的时段之一,特价机票往往成为人们关注的焦点。在这个数字化时代,利用爬虫技术获取特价机票信息已成为一种常见的策略。通过结合C#和Fizzler库,我们可以更加高效地实现这一目标&…

20240502在WIN10下给X99平台上的M6000显卡安装驱动程序

20240502在WIN10下给X99平台上的M6000显卡安装驱动程序 2024/5/2 9:32 人工智能计算领域的领导者 | NVIDIA https://www.nvidia.cn/ C:\NVIDIA\DisplayDriver\552.22\Win11_Win10-DCH_64\International IMPORTANT NOTICE -- READ CAREFULLY: -------------------------------…

pmp培训机构哪个比较好,求推荐-

寻找一个自己认为比较好的PMP培训机构千万不要盲目,先在网上看看大家都推荐什么,看一下各个机构的老学员反馈,这些对我们的选择有非常大的帮助,最起码有了一些风评上的参考,现状就是目前线上机构的竞争比较大&#xff…

c语言从入门到函数速成(1)

温馨提醒:本篇文章适合人群:刚学c又感觉那个地方不怎么懂的同学以及以及学了一些因为自身原因停学一段时间后又继续学c的同学 好,正片开始。 主函数 学c时最先学的是我们c语言程序的主体函数,c的主函数有两种写法,这…

【JavaEE】Thread的方法和属性

文章目录 1、Thread的常见构造方法2、Thread的几个常见属性2.1 ID2.2 名称2.3 状态2.4 优先级2.5 是否后台线程2.6 是否存活2.7 是否被中断 3.补充说明3.1 Thread.sleep()的作用3.2 Thread.sleep()的异常处理方式 1、Thread的常见构造方法 方法说明Thread()创建线程对象Thread…

动态规划-子序列问题1

文章目录 1. 最长递增子序列(300)2. 摆动序列(376)3. 最长递增子序列的个数(673)4. 最长数对链(646) 1. 最长递增子序列(300) 题目描述: 状态表…

Linux 进程间通信之命名管道

💓博主CSDN主页:麻辣韭菜💓   ⏩专栏分类:Linux知识分享⏪   🚚代码仓库:Linux代码练习🚚   🌹关注我🫵带你学习更多Linux知识   🔝 目录 前言 命名管道 创建一个命名管道 …