一条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状态

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL的索引使用的数据结构,事务知识

一、索引的数据结构🌸 索引的数据结构(非常重要) mysql的索引的数据结构,并非定式!!!取决于MySQL使用哪个存储引擎 数据库这块组织数据使用的数据结构是在硬盘上的。我们平时写的代码是存在内存…

根据今天全量的数据以及昨天全量的数据,获取今天增量的数据

编写了一个根据今天的全量的数据以及昨天全量的数据,自动获取今天增量数据的脚本。 #!/bin/bashhive_db"" hive_result_tb"" hive_source_tb"" hive_source_last_tb"" hive_pk""initParam(){# 库名hive_db${1}# …

Qt中JSON的使用

一.前言: JSON是一种轻量级数据交换格式,常用于客户端和服务端的数据交互,不依赖于编程语言,在很多编程语言中都可以使用JSON,比如C,C,Java,Android,Qt。除了JSON&#x…

前端实现给图片添加水印

一、利用Canvas ::: tip 实现步骤: 上传图片,转换为base64格式的数据,利用Image加载图片利用canvas写入图片,然后绘制水印最后通过canvas输出添加水印后的base64数据 ::: 1. 本地读取图像文件渲染到img标签 ::: tip ​ 通过intpt[type…

格力变频空调怎么收氟?

格力变频空调怎么收氟? 随着气温的升高,越来越多的人开始使用格力变频空调来调节室内温度。但是,在使用格力变频空调时,很多人并不知道如何正确收氟。下面,我们将详细介绍一下格力变频空调怎么收氟。 首先&#xff0…

MyCat核心概念、需求案例讲解、环境准备及分片配置

1.MyCat概念介绍 2.MyCat入门需求 2.1 需求分析 2.2 环境准备 输入以下命令检查服务器防火墙状态 dead代表关闭状态,如果不关闭也可以需要开放特定的端口号!! systemctl status firewalld接着需要在三台服务器上的MySQL上创建三个数据库db0…

企业架构NOSQL数据库之MongoDB

目录 一、背景描述及其方案设计 (一)业务背景描述 (二)模拟运维设计方案 二、Mongodb介绍 (一)nosql介绍 (二)产品特点 1、存储性 2、 效率性 3、结构 三、安装和配置 (一&#xff09…

Leetcode-每日一题【剑指 Offer 10- I. 斐波那契数列】

题目 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下: F(0) 0, F(1) 1 F(N) F(N - 1) F(N - 2), 其中 N > 1. 斐波那契数列由 0 和 1 开…

考研C语言进阶题库——更新6-10题

目录 6输入一个字符串,输出其中字母的个数 7用递归求函数值x1,f(x)10,x>1.f(x)f(x-1)2 8所给字符串正序反序连接,形成新串并输出 9输入若干个整数以-1标记为结束输出其中的最大值 10求矩阵的两条对角线之和 6输入一个字符串,输出其中…

[openCV]基于赛道追踪的智能车巡线方案V1

import cv2 as cv import os import numpy as npimport time# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir:文件夹根目录输入 ext: 扩展名返回: 文件路径列表""&quo…

Golang map 常用方法

文章目录 前言按key排序按value排序统计字符串中元素重复出现次数并将结果排序返回 前言 由于map是无序的,所以排序成 slice 返回,且都使用泛,代码只是示例,省略了错误判断 按key排序 package mainimport "fmt"func example[T c…

C语言刷题------(1)

C语言刷题 博主用的刷题网站:题库 - 蓝桥云课 (lanqiao.cn) 小伙伴们可以去试试!!! First question 题目:成绩统计 题目描述:小蓝给学生们组织了一场考试,卷面总分为 100 分,每…

K3s vs K8s:轻量级对决 - 探索替代方案

在当今云原生应用的领域中,Kubernetes(简称K8s)已经成为了无可争议的领导者。然而,随着应用规模的不断增长,一些开发者和运维人员开始感受到了K8s的重量级特性所带来的挑战。为了解决这一问题,一个名为K3s的…

深入解析Spring MVC注解:@PathVariable、@ResponseBody和@RequestParam的用法和区别

简介 在Spring MVC框架中,PathVariable、ResponseBody和RequestParam是常用的注解,它们分别用于处理请求的路径变量、响应数据格式和请求参数。本文将深入介绍这些注解的用法,并详细讨论它们之间的区别,以便开发者在构建Web应用程…

【软件测试】一份合格的软件测试简历长什么样?

你可以写一篇出众的软件测试简历并且这篇测试用例能够为你带来面试电话么?如果没有,请继续阅读。我敢肯定,读完这篇文章,你将能够写出一个完美的杀手级别的软件测试和质量保证的简历,这将为你带来面试电话。 你的简历是…

如何在轻量级RTSP服务支持H.264扩展SEI发送接收自定义数据?

为什么开发轻量级RTSP服务? 开发轻量级RTSP服务的目的是为了解决在某些场景下用户或开发者需要单独部署RTSP或RTMP服务的问题。这种服务的优势主要有以下几点: 便利性:通过轻量级RTSP服务,用户无需配置单独的服务器,…

CentOS6如何进入单用户模式

问题:因为挂载有问题,开机启动不了,需要进入单用户模式进入修改fstab挂载文件。 1、Linux系统开机,在3秒内按下啊e,然后跳转到内核界面。 2、再按下e进入如下界面,选择kernel的一项,然后按下e键…

视频安防监控EasyCVR平台海康大华设备国标GB28181告警布防的报文说明

TSINGSEE青犀视频监控综合管理平台EasyCVR基于云边端协同,可支持海量视频的轻量化接入与汇聚管理。平台既具备传统安防视频监控的能力,比如:视频监控直播、云端录像、云存储、录像检索与回看、告警上报、平台级联、云台控制、语音对讲等&…

mysql的索引

在 MySQL 中,可以在建表语句中使用主键索引、唯一索引和普通索引来定义表的索引 主键索引: 主键索引用于唯一标识表中的每一行数据,通常用于加速根据主键值进行数据检索的操作。在建表时,可以通过 PRIMARY KEY 关键字定义主键索引…

深度学习Redis(2):持久化

前言 在上一篇文章中,介绍Redis的内存模型,从这篇文章开始,将依次介绍Redis高可用相关的知识——持久化、复制(及读写分离)、哨兵、以及集群。 本文将先说明上述几种技术分别解决了Redis高可用的什么问题;然后详细介绍Redis的持…