一条Update语句的执行过程是怎样的?

前言

通过本文主要了解Sql执行流程,包括两个问题:

MySQL的一条Select语句是怎么运行的?

MySQL的一条Update语句是怎么运行的?

先看第一个问题,这里做个简单描述 ,因为我们着重还是看Update

MySQL执行一条Select语句是怎么运行的?

这个问题大家在面试的时候大家都背过类似的题,而且网上也有很多答案,这里分享一个大致流程介绍,关于下图的介绍来自这里 执行一条 select 语句,期间发生了什么?

  1. 连接器:建立连接,管理连接、校验用户身份;
  2. 查询缓存:查询语句如果命中查询缓存则直接返回,否则继续往下执行。MySQL 8.0 已删除该模块;
  3. 解析 SQL,通过解析器对 SQL 查询语句进行词法分析、语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;
  4. 执行 SQL:执行 SQL 共有三个阶段:
  5. 预处理阶段:检查表或字段是否存在;将 select * 中的 * 符号扩展为表上的所有列。
  6. 优化阶段:基于查询成本的考虑, 选择查询成本最小的执行计划;
  7. 执行阶段:根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端

相对于Select,内容更多和更复杂的是Update语句的执行,接下来我们讲展开细讲,再看本文之前可以先看看之前的分享,这两篇文章对Double Write和Buffer Pool有做详细的介绍:

MySQL的Double Write如何保证可靠性?

InnoDB的Buffer Pool是如何管理数据页的?

当然最好也了解下 redolog、undolog、binlog的相关知识点,这块知识我们会在后续继续分享!

Update执行逻辑

先把我画的图看完,图中步骤比较多,需要花点时间看,你想我画这个肯定花了更长时间,如果觉得还不错的话,谢谢点赞收藏下,不足的话大家指正下!

执行流程图:

整个流程的架构很清晰:Client客户端、Server层、InnoDB引擎层、磁盘,这里就不对每个组件的具体功能和细节处理做更详细的解释了,文章主要是帮我们把流程理清楚!

核心组成部分

当然这里也涉及到几个核心:Buffer Pool、Double Write、Redo Log、Undo Log、BinLog、WAL

Buffer Pool和Double Write可以参考我之前的文章,在开头就有分享原文链接,我们来看以下问题!

Redo Log、Undo Log、BinLog分别存的什么内容,分别是做什么用的?

Redo Log 在引擎层实现,用来恢复数据的,保障已提交事务的持久化特性,记录的是物理级别的数据页(包括data page和undo page)做的修改

Undo Log 在引擎层实现的逻辑日志,用于数据回滚到之前状态,对于每个UPDATE语句,对应一条相反的UPDATE的undo log

BinLog 是Server实现的逻辑日志,用于复制和恢复数据,记录了所有的 DDL 和 DML 语句(除了数据查询语句select、show等)

WAL是什么,哪里用到了它?

WAL全称为Write-Ahead Logging,预写日志系统。主要写undo log、redo log、binlog这些用到了。

真正使用WAL的原因是:磁盘的写操作是随机IO,比较耗性能,所以如果把每一次的更新操作都先写入log中,那么就成了顺序写操作,实际更新操作由后台线程再根据log异步写入

UndoLog会存储在哪些地方?

我们从图中也可以清晰的知道UndoLog在两个地方:Buffer Pool中的undo page页,和磁盘中的表共享空间的Undo log

详解执行流程

看完执行流程图大家都有个大概印象了,我们分三个部分进行更具体的文字化描述,一起来看看吧!

Client客户端:

  1. 客户端通过tcp/ip发送一条sql语句到server层

Server层:

  1. 接收客户端过来的请求,进行权限验证
  2. 权限验证通过后,解析器会对SQL语句进行词法、语法分析等
  3. 经过验证解析的SQL语句会在优化器生成选择最优执行计划
  4. 然后执行器将会执行经过优化的SQL语句

Server层和存储引擎之间怎么通信的呢?

到这里用户发送的一个SQL已经经过各种验证、分析、优化到了执行阶段,那么接下来就是执行器怎么和InnoDB存储引擎打交道了。

对于Server层来说,它是不知道存储引擎的实现细节的,而是通过定义的API接口和存储引擎通信。可以理解为存储引擎是一个类,然后每个实例(InnoDB)都通过一个特殊的处理程序接口与MySQL服务器通信。

InnoDB引擎层:

  1. 现在已经到了引擎层了,存储引擎主要负责数据的存储和读取
  2. 调用存储引擎接口后,会先从Buffer Pool获取数据页,如果没有就从磁盘中读入Buffer Pool,然后判断更新前后的记录是否一样
  3. 开启事务,修改数据之前先记录undo log,写入Buffer Pool的undo page
  4. 开始更新page data中的记录,被修改的数据页称为脏页,修改会被记录到内存中的 redo log buffer中,再刷盘到磁盘的redo log文件,此时事务是 perpare阶段
  5. 这个时候更新就完成了,当时脏页不会立即写入磁盘,而是由后台线程完成,这里会用double write来保证脏页刷盘的可靠性
  6. 还没结束呢,这时候可以通知Server层,可以正式提交数据了, 执行器记录binlog cache,事务提交时才会将该事务中的binglog刷新到磁盘中
  7. 这个时候Update语句完成了Buffer Pool中数据页的修改、undo日志、redo log缓存记录,以及记录binlog cache缓存
  8. commit阶段,这个阶段是将redo log中事务状态标记为commit
  9. 此时binlog和redo log都已经写入磁盘,如果触发了刷新脏页的操作,先把脏页copy到double write buffer里,Double Write Buffer 的内存数据刷到磁盘中的共享表空间 ibdata,再刷到数据磁盘上数据文件 ibd
  10. 流程完结

什么是二阶段提交?

二阶段提交,顾名思义,会包含 2 个阶段:

prepare 阶段,协调器会询问所有执行器,是否可以提交事务

commit 阶段,协调器会通知执行器进行提交操作

update的执行阶段也用到了,比如:

prepare 阶段:将 redo log 对应的事务状态设置为 prepare,然后将 redo log 刷新到硬盘;

commit 阶段:将 binlog 刷新到磁盘,接着调用引擎的提交事务接口,将 redo log 状态设置为 commit(将事务设置为 commit 状态后,刷入到磁盘 redo log 文件)

总结

今天的分享就到这了,我们平时一条Update语句其实内部会经历很多流程,语句解析、日志WAL,Buffer Pool等。通过今天这篇文章的分享相信大家对流程已经很清晰了,后续将继续带来Redo Log、UndoLog等内容,敬请期待!

#mysql八股文##Mysql##存储引擎##select##Update#
全部评论

相关推荐

03-19 19:52
已编辑
桂林理工大学 后端
#牛客AI配图神器# 1.在做项目的过程中,你得清楚自己掌握了哪一块,对你来说哪一块比较容易上手?2.那些项目是用来学习的。学完之后,有没有自己去挑战做一些小系统,实现一些功能键呢?3.那从技术角度来说,你对自己掌握的技术栈有什么认知?比如你刚才说的项目,涉及大模型、文生图、智能 APP 等功能,这些是通过什么技术构建出来的呢?要是直接下载现成的项目,跑通了也没真正掌握技术。4.比如说用到大模型,本地部署之后,怎么让它读懂我们的信息,怎么和大模型沟通并得到反馈结果呢?这中间肯定需要技术和框架来支持。假如用千问开源的大模型,下载到本地部署后,通过应用载体怎么和它交互呢?5.我就是想了解你在技术方面,尤其是框架技术上的掌握程度,它们都用在哪些地方、有什么作用。你现在是不是主要关注一些基础代码知识呢?作为一名纯开发人员,你能不借助开源系统,自己一步一个脚印敲代码吗?6.工作的时候,你有没有兴趣去拓展一些知识点呢?看视频学习会不会让你这里学一点、那里学一点,不够系统?7.那现在如果做二次开发,对你来说难度大吗?8.还有关于模型的运用,你现在习惯怎么运用?遇到技术难点时,你会怎么做?9.在开发过程中,没有现成的经验,只能摸索,也没有视频可以参考,只能靠自己现有的知识储备。我举个例子,比如想实现登录功能,你要怎么做?在你没做过的情况下,怎么解决这个问题,怎么一步步实现这个功能?像用户登录板块,你在没做过的情况下,怎么建立起来,怎么找思路?你现在做过了肯定知道,但如果是没做过的功能,你怎么实践?10.没做过的东西,要清楚有哪些步骤、路线和难题,这样才能去解决。要是连困难都不知道是什么,就很难解决问题。比如说要实现用户微信登录功能,需要涉及哪些连接、数据库和板块,怎么实现,怎么把它们连接起来?如果连方向都没有,知识储备也不够,这种情况下你觉得该怎么办?#初创公司值得加入吗?# #面经#
点赞 评论 收藏
分享
评论
5
5
分享

创作者周榜

更多
牛客网
牛客企业服务