这篇文章带你了解sql语句是怎么执行的

2023-11-09


在这里插入图片描述

mysql有各种版本的架构图,但基本上都可以分为Server层和存储引擎层

一、mysql架构分析

下面是mysql的一个简要架构图:

在这里插入图片描述
Server层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog日志模块。
存储引擎: 主要负责数据的存储和读取,采用可以替换的插件式架构,支持InnoDB、MyISAM、Memory等多个存储引擎,其中InnoDB引擎有自有的日志模块redolog 模块。
InnoDB 5.5.5版本作为默认引擎。

  • 连接器
    主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。
  • 查询缓存
    连接建立后,执行查询语句的时候,会先查询缓存,Mysql会先校验这个sql是否执行过,以Key-Value的形式缓存在内存中,Key是查询预计,Value是结果集。如果缓存key被命中,就会直接返回给客户端,如果没有命中,就会执行后续的操作,完成后也会把结果缓存起来,方便下一次调用当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。
    Mysql 查询不建议使用缓存,因为对于经常更新的数据来说,缓存的有效时间太短了,往往带来的效果并不好,对于不经常更新的数据来说,使用缓存还是可以的,Mysql 8.0 版本后删除了缓存的功能,官方也是认为该功能在实际的应用场景比较少,所以干脆直接删掉了。
  • 分析器
    mysql 没有命中缓存,那么就会进入分析器,分析器主要是用来分析SQL语句是来干嘛的,分析器也会分为几步:
    第一步,词法分析,一条SQL语句有多个字符串组成,首先要提取关键字,比如select,提出查询的表,提出字段名,提出查询条件等等。做完这些操作后,就会进入第二步。
    第二步,语法分析,主要就是判断你输入的sql是否正确,是否符合mysql的语法。
    完成这2步之后,mysql就准备开始执行了,但是如何执行,怎么执行是最好的结果呢?这个时候就需要优化器上场了。
  • 优化器
    优化器的作用就是它认为的最优的执行方案去执行(虽然有时候也不是最优),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。
  • 执行器
    当选择了执行方案后,mysql就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果

二、语句分析

2.1 查询语句

说了以上这么多,那么究竟一条sql语句是如何执行的呢?其实我们的sql可以分为2种,一种是查询,一种是更新(增加,更新,删除)。我们先分析下查询语句,语句如下:

select * from tb_student  A where A.age='18' and A.name='张三';
  1. 结合上面的说明,我们分析下这个语句的执行流程:
    先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在mysql8.0版本以前,会先查询缓存,以这条sql语句为key在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。

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

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

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

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

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

2.2 更新语句

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

update tb_student A set A.age='19' where A.name='张三';

我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。其实条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,mysql 自带的日志模块式binlog(归档日志),所有的存储引擎都可以使用,我们常用的InnoDB引擎还自带了一个日志模块redo log,我们就以InnoDB模式下来探讨这个语句的执行流程。流程如下:

  1. 先查询到张三这一条数据,如果有缓存,也是会用到缓存。
  2. 然后拿到查询的语句,把 age 改为19,然后调用引擎API接口,写入这一行数据,InnoDB引擎把数据保存在内存中,同时记录redo log,此时redo log进入prepare状态,然后告诉执行器,执行完成了,随时可以提交。
  3. 执行器收到通知后记录binlog,然后调用引擎接口,提交redo log 为提交状态。
  4. 更新完成。

问题

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

  • 这就是之前mysql的模式了,MyISAM引擎是没有redo log的,那么我们知道它是不支持事务的,所以并不是说只用一个日志模块不可以,只是InnoDB引擎就是通过redo log来支持事务的。

用两个日志模块,但是不要这么复杂行不行,为什么redo log 要引入prepare预提交状态?这里我们用反证法来说明下为什么要这么做?

  • 先写redo log 直接提交,然后写 binlog,假设写完redo log 后,机器挂了,binlog日志没有被写入,那么机器重启后,这台机器会通过redo log恢复数据,但是这个时候bingog并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。

  • 先写binlog,然后写redo log,假设写完了binlog,机器异常重启了,由于没有redo log,本机是无法恢复这一条记录的,但是binlog又有记录,那么和上面同样的道理,就会产生数据不一致的情况。

  • 如果采用redo log 两阶段提交的方式就不一样了,写完binglog后,然后再提交redo log就会防止出现上述的问题,从而保证了数据的一致性。

有没有一个极端的情况呢?假设redo log 处于预提交状态,binglog也已经写完了,这个时候发生了异常重启会怎么样呢?

  • 判断redo log 是否完整,如果判断是完整的,就立即提交。
  • 如果redo log 只是预提交但不是commit状态,这个时候就会去判断binlog是否完整,如果完整就提交 redo log, 不完整就回滚事务。
  • 这样就解决了数据一致性的问题。

三. 总结

  • Mysql 主要分为Server曾和引擎层,Server层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用。
  • 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory等。
  • sql等执行过程分为两类,一类对于查询等过程如下:权限校验—》查询缓存—》分析器—》优化器—》权限校验—》执行器—》引擎
  • 对于更新等语句执行流程如下:分析器----》权限校验----》执行器—》引擎—redo log prepare—》binlog—》redo log commit

END!!! 如果这篇文章对你有用的话,不胜感激!!!
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

这篇文章带你了解sql语句是怎么执行的 的相关文章

  • 为什么我的 if 语句没有按我预期的方式工作?

    我正在尝试实现以下目标 我向我的 SQL 数据库询问使用SELECT FROM subjects 这样做之后我要求使用数组mysqli fetch assoc 在那之前一切都很好 现在的问题是 当我尝试在每个循环中修改 genero 的值
  • 无法通过套接字“/var/lib/mysql/mysql.sock”连接到本地 MySQL 服务器 (2)

    当我尝试连接 mysql 时出现以下错误 Can t connect to local MySQL server through socket var lib mysql mysql sock 2 这个错误有解决办法吗 其背后的原因可能是什
  • MySQL PHP邮政编码比较具体距离

    我试图找出比较一个邮政编码 用户提供的 和一大堆其他邮政编码 现在大约有 200 个邮政编码 之间的距离的最有效方法 相对于加载时间 但它会随着时间的推移而增加 我不需要任何精确的东西 只是在球场上 我下载了整个美国的邮政编码 csv 文件
  • 独立对列进行排序,使得所有空值都位于每列的最后

    这是一个名为的示例表animal name color fox brown fox red dog gold 现在 我想要的是这样的结果 fox dog brown gold red 名称应该是结果的列 不同颜色值作为行 我的第一个想法是
  • 在sqlite SQL语句中与order by子句结合使用limit

    下面的两条 SQL 语句总是会产生相同的结果集吗 1 SELECT FROM MyTable where Status 0 order by StartTime asc limit 10 2 SELECT FROM SELECT FROM
  • 列中差异的数量

    我想检索一列每行中有多少个字母的差异 例如 如果您有一个值 test 而另一行有一个值 testing 则 test 和 testing 之间的差异为 4 个字母 该列的数据值为 4 I have reflected about it an
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • sql server 按组排名

    问题看似简单 但我却无法理解 这是针对 sql 服务器的 what I have in a table What I need as a output cksum id cksum id 2162514679 204 2162514679
  • 如何在 PostgreSQL 中使用具有多个值的 SQL LIKE 条件?

    有没有更短的方法来查找多个匹配项 SELECT from table WHERE column LIKE AAA OR column LIKE BBB OR column LIKE CCC 这个问题适用于 PostgreSQL 9 1 但如
  • 如何从 PostgreSQL 中的时间戳列值提取一天中的时间(或小时)?

    我正在尝试从 PostgreSQL 中的 时间戳 列中提取一天中的时间 这是我的做法 但是 太糟糕了 知道如何做得更好吗 SELECT date part hour date demande text hours date part min
  • SELECT 语句会受到 SQL 注入攻击吗?

    实际上有2个问题 我知道我必须尽可能多地使用存储过程 但我想知道以下内容 A 我可以从 SELECT 语句 例如 Select from MyTable 获得 SQL 注入攻击吗 B 另外 当我在 ASP NET 中使用 SQLDataSo
  • 内连接不重复,可以吗?

    鉴于这两个表 表 A1 有两行具有相同的值 a A1 a a 表 A2 有两行主键值为 A B 它们与 a 关联 A2 PK col2 A a B a 我想要的是 A1 和 A2 的连接并得到这个结果 a A a B 显然内连接在这里不起作
  • 如何将表中不存在但原始SQL中存在的实体字段设置为别名?

    假设我们有一个这样的查询 SELECT CUSTOM EXPRESSION as virtualfield FROM users 用户的实体本身具有 虚拟字段 但映射注释没有 因为表没有该字段 假设它作为原始 SQL 执行 我们如何使用上面
  • 月份增量查询

    我想通过添加 1 个月来更新数据库中的月份 但我不知道如何在以下存储过程查询中添加月份 我不擅长 sql 请检查它 ALTER PROCEDURE dbo ChangePassword password varchar 20 epasswo
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 计算运行总计时出错(之前期间的累计)

    我有一张桌子 我们称之为My Table有一个Created日期时间列 在 SQL Server 中 我试图提取一个报告 该报告显示历史上有多少行My Table按月在特定时间 现在我知道我可以显示有多少added每个月 SELECT YE
  • 在 PHP 字符串中格式化 MySQL 代码

    是否有任何程序 IDE 可以在 PHP 字符串中格式化 MySQL 代码 例如 我使用 PHPStorm IDE 但它无法做到这一点 它对 PHP 和 MYSQL 执行此操作 但不适用于 php 字符串内的 MYSQL 我已准备好使用新的
  • MS ACCESS 计数/求和行数,不重复

    我有下表 我需要计算总行数而不包括任何重复记录 CustomerID test1 test1 test2 test3 test4 test4 如您所见 总行数为 6 但有两个 test1 和两个 test4 我希望查询返回 4 IOW 我想
  • 索引数量越少意味着插入、更新和删除速度更快? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 Oracle 行的多个列上使用透视

    我在 Oracle 表中有以下示例数据 tab1 我正在尝试将行转换为列 我知道如何在某一列上使用 Oracle 数据透视表 但是否可以将其应用于多个列 样本数据 Type weight height A 50 10 A 60 12 B 4

随机推荐

  • 听说现在流行卷应用?开发者们都开始调用文心API开发了?!

    随着大模型的涌现 我们喜悦于其远远超越小模型的性能 但又不得不面临大模型开发难的困境 训练难 微调难 部署难 开发者难以将其投入实际生产 不仅面临资源的限制 更面临高精数据难寻 时间成本过高等问题 为了让平台更多开发者可以进行大模型开发 体
  • vue import..from..说明

    import Vue from vue import axios from axios import App from App import store from store import router from router import
  • Java中IO流——详解字节流之FileOutputStream和FileInputStream

    文章目录 前言 一 Java流的概述 二 常用字节流分类 1 字节输出输入流 1 FileOutputStream 2 FileInputStream 3 复制小练习 4 异常捕获 总结 前言 我们之前学习了Java中的异常机制和File类
  • 【区块链】Python开发EOS机器人与WAX链游脚本常用工具

    前言 众所周知 开发EOS机器人与WAX链游脚本 我们都需要调用eosio chain api https developers eos io manuals eos latest nodeos plugins chain api plug
  • mybatis多表联查sql用法示例

    用到sql变量 sql复用
  • ssm打印sql如何开启_ssm环境下配置log4j打印mybatis的sql语句

    首先附上官网的说明文档 mybatis Logging 环境spring4 3 0 springmvc4 3 0 mybatis3 4 0 按官方文档的说明 1 SLF4J 2 Apache Commons Logging 3 Log4j
  • 使用invoke方法解决跨线程访问的问题

    C 中禁止跨线程直接访问控件 InvokeRequired是为了解决这个问题而产生的 当一个控件的InvokeRequired属性值为真时 说明有一个创建它以外的线程想访问它 获取一个值 该值指示调用方在对控件进行方法调用时是否必须调用 I
  • js+bootstrap+jquery+vue实现房贷计算器

    代码链接 loan 使用vue js html css实现房贷的计算 版权声明 本文为CSDN博主 小样还想跑 的原创文章 遵循CC 4 0 BY SA版权协议 转载请附上原文出处链接及本声明
  • 23 种设计模式详解(全23种)

    设计模式的分类 总体来说设计模式分为三大类 创建型模式 共五种 工厂方法模式 抽象工厂模式 单例模式 建造者模式 原型模式 结构型模式 共七种 适配器模式 装饰器模式 代理模式 外观模式 桥接模式 组合模式 享元模式 行为型模式 共十一种
  • 人手一份核武器:Android手机装Kali Linux

    首先这是安卓手机的专属工具 因为Android基于Linux 所以就有了得天独厚的优势 1 先下载好Linux Deploy 前提是本手机已root 2 按下图配置 不过有地方需要说明 Distribute Suite已经改为sana 但无
  • Windows Server 2012 R2 设置 smtp 服务器

    Windows Server 2012 2012 R2 安装和配置 SMTP 服务器 安装 SMTP 服务器 以下是安装 SMTP 服务器功能的步骤 打开 服务器管理器 单击键盘上的 Windows 按钮 输入 服务器管理器 在 结果 窗口
  • FW-1设备配置命令

    DCFW 1800 config hostname FW 1 FW 1 config ip vrouter trust vr FW 1 config vrouter ip route 0 0 0 0 0 202 11 33 26 FW 1
  • cmd创建用户并初始化新用户桌面

    author skate time 2013 12 20 功能 在win2003上创建用户 并初始化新用户的桌面 echo InternetShortcut gt gt MysqlTool url echo URL C Program Fi
  • Qt之pro配置多个子工程/子模块

    简述 进行Qt项目开发的时候 尤其是大型项目 经常涉及多工程 多模块问题 其主要思想还是模块化 目的是为了降低程序复杂度 使程序设计 调试和维护等操作简单化 简述 配置 效果 多工程 多模块 更多参考 配置 效果 多工程 如果需要管理多工程
  • JavaMap集合&Stream流

    1 Map集合 1 1Map集合概述和特点 Map集合概述 interface Map
  • Python-Thread(通俗易懂)

    此类表示在单独的控制线程中运行的活动 有两种方法可以指定该活动 一是将可调用对象传递给构造函数 二是通过覆盖子类中的run 方法 如果你对线程不太理解 我们可以打个比方 把线程数看作车辆数 我们来完成一个简单的客运运输工作 以下为了方便理解
  • 第8届Python编程挑战赛初赛真题剖析-2022年全国青少年信息素养大赛

    导读 超平老师计划推出 全国青少年信息素养大赛Python编程真题解析 50讲 这是超平老师解读Python编程挑战赛系列的第1讲 全国青少年信息素养大赛 原全国青少年电子信息智能创新大赛 是 世界机器人大会青少年机器人设计与信息素养大赛
  • VC++ MapWinGis篇(二)

    添加高德图层 ArcGisProvider h pragma once include BaseProvider h class ArcGisBaseProvider public BaseProvider public ArcGisBas
  • Java RMI 远程代码执行漏洞

    0x01 漏洞描述 Java RMI 远程代码执行漏洞 Java RMI服务是远程方法调用 是J2SE的一部分 能够让程序员开发出基于JAVA的分布式应用 一个RMI对象是一个远程Java对象 可以从另一个Java虚拟机上 甚至跨过网络 调
  • 这篇文章带你了解sql语句是怎么执行的

    一条sql语句是怎么执行的 一 mysql架构分析 二 语句分析 2 1 查询语句 2 2 更新语句 三 总结 mysql有各种版本的架构图 但基本上都可以分为Server层和存储引擎层 一 mysql架构分析 下面是mysql的一个简要架