MySQL:更新语句执行流程详解

其实更新语句update和查询语句“大同小异”,但关键的几个差异点,恰恰是面试常考、工作中容易踩坑的地方,尤其是redo log、binlog和两阶段提交,看完这篇彻底搞懂!

先给大家一个核心结论:MySQL的update语句,会完整走一遍查询语句的核心流程,但在“查询缓存”“执行器后续操作”这两个环节,有明显区别。下面我们结合具体案例(update user set name = 'xiaoming' where id = 1),一步步拆解全流程,查漏补缺,保证每个细节都准确可落地。

01更新语句vs查询语句通用核心流程

不管是select还是update,客户端发起请求后,都会先经过MySQL的“上层服务层”(连接器、解析器、预处理器等),这部分流程完全一致,接下来我们通过在之前聊过的select流程基础上,快速过一遍,重点标注和查询语句的细微差异。

1. 连接器:建立连接,校验身份(和查询一致)

  • 客户端要执行任何SQL语句,第一步都要通过连接器和MySQL服务器建立连接。连接器会做两件关键事:

  • 接收客户端的用户名、密码,校验身份是否合法(比如密码错误会直接拒绝连接);

  • 身份校验通过后,分配一个线程负责处理这个客户端的后续请求,直到客户端主动断开连接(或超时断开)。

这里和查询语句完全一样,不管是查还是更,连接是基础,没有合法连接,后续所有操作都无法执行。

2. 查询缓存:更新语句不使用,但会“清空缓存”(关键差异点1)
这是更新语句和查询语句第一个核心区别,也是查询缓存被MySQL 8.0移除的核心原因,一定要记牢:

  • 查询语句(select)会先检查查询缓存,如果缓存中存在“完全匹配”的SQL结果,会直接返回,跳过后续解析、优化等流程;

  • 更新语句(update)不会使用查询缓存,但只要执行了更新语句(哪怕是更新一张和缓存无关的表),MySQL会直接清空这张表的所有查询缓存。

举个例子:你刚执行过select * from user where id = 1,结果被缓存起来了;但此时有人执行了update user set name = 'test' where id = 2,哪怕只更新了id=2的记录,user表的所有查询缓存都会被清空。

这就导致查询缓存的“命中率极低”,尤其是高并发场景下,更新操作频繁,缓存刚存上就被清空,反而会消耗内存和CPU,完全得不偿失。所以MySQL 8.0直接移除了查询缓存功能,后续版本再也不用考虑这个环节了。

3. 解析器:词法+语法分析,构建语法树(和查询一致)
跳过查询缓存后,SQL语句会进入解析器,解析器的核心作用是“看懂”SQL语句,具体分为两步:

  • 词法分析:识别SQL中的关键字、表名、字段名、值等。比如解析update user set name = 'xiaoming' where id = 1时,会识别出“update”是关键字、“user”是表名、“name”是字段名、“xiaoming”是更新后的值、“id”是条件字段;

  • 语法分析:校验SQL语句是否符合MySQL的语法规则。比如如果把“update”写成“updata”,解析器会直接报错“语法错误”,终止执行。

解析完成后,解析器会生成一棵“语法树”,把SQL的逻辑结构转化为MySQL能理解的格式,传递给下一个环节——预处理器。

4. 预处理器:校验表和字段的合法性(和查询一致)
语法树生成后,会进入预处理器,预处理器主要做“合法性校验”,避免后续执行时出现“表不存在”“字段不存在”的错误:

  • 校验SQL中涉及的表(比如user表)是否存在;

  • 校验表中的字段(比如name、id)是否存在;

  • 校验字段和值的类型是否匹配(比如id是int类型,就不能把它更新成字符串)。

如果校验失败,会直接返回错误;校验通过后,语法树会被优化,进入下一个核心环节——优化器。

5. 优化器:选择最优执行计划(和查询一致)
MySQL的优化器是“智能大脑”,它的核心作用是:在多种可能的执行方式中,选择效率最高的一种,生成执行计划。

比如我们的案例update user set name = 'xiaoming' where id = 1,where条件中的id是主键索引——优化器会判断:“通过主键索引查找id=1的记录,是最快的方式”,于是确定执行计划:使用id主键索引定位目标记录。

这里和查询语句的逻辑一致:优化器会根据索引、数据量等信息,选择最优路径,避免“全表扫描”等低效操作。

6. 执行器:调用存储引擎,执行具体操作(差异点的开始)
执行计划确定后,就轮到执行器上场了。执行器的核心作用是“调用存储引擎的接口,完成具体的读写操作”——查询语句的执行器,调用存储引擎接口是“读取数据”;而更新语句的执行器,调用接口是“修改数据”,这也是后续所有差异的起点。

重点来了:执行器调用存储引擎(比如InnoDB)后,更新操作才真正进入“核心环节”——涉及undo log、redo log、脏页、binlog、两阶段提交等,这些都是查询语句没有的流程。

02更新一条记录的8步核心细节

结合案例update user set name = 'xiaoming' where id = 1,我们详细拆解执行器和InnoDB存储引擎协同工作的全过程,每一步都标注关键细节和底层逻辑,帮大家查漏补缺,避免理解偏差。

步骤1:定位目标记录,加载到内存(缓冲池)

执行器首先调用InnoDB的接口,根据优化器确定的“主键索引查找”计划,定位id=1的记录,这里分两种情况:

  • 如果id=1所在的数据页,已经在InnoDB的buffer pool(缓冲池)中(也就是之前被读取过,缓存到内存中了),直接从内存中取出这条记录,返回给执行器;

  • 如果数据页不在buffer pool中,InnoDB会从磁盘中读取该数据页,加载到buffer pool中,再将记录返回给执行器。

这里有个关键知识点:buffer pool是InnoDB的“内存缓存”,目的是减少磁盘I/O(磁盘读写速度比内存慢1000倍以上),所有读写操作都会先操作内存中的数据,后续再异步同步到磁盘。

步骤2:校验更新前后是否一致,避免无效更新
执行器拿到InnoDB返回的聚簇索引记录后,会先做一次“无效更新校验”:对比更新前的记录(比如原来name是‘zhangsan’)和更新后的记录(name是‘xiaoming’),如果两者完全一致,就直接终止后续流程,不做任何更新操作——这是MySQL的一个优化,避免无效的磁盘和日志写入。

只有当更新前后的记录不一致时,执行器才会将“旧记录”和“新记录”都作为参数,传给InnoDB,让InnoDB执行真正的更新操作。

步骤3:开启事务,记录undo log(用于回滚)
InnoDB接收到执行器的更新请求后,首先会开启一个事务(如果当前没有主动开启事务,MySQL会自动开启一个隐式事务),然后立即记录undo log(回滚日志)——这是保证事务原子性(ACID中的A)的核心。

具体来说:因为是update操作,InnoDB会将被更新列的“旧值”记录到undo log中(比如记录“user表id=1的name旧值是‘zhangsan’”),undo log会先写入buffer pool的Undo页面(内存中),同时会记录对应的redo log(后续步骤4会讲)。

关键细节:undo log的作用是“回滚”——如果后续事务执行失败(比如断电、报错),MySQL可以通过undo log恢复到更新前的状态,保证数据一致性;另外,undo log还用于MVCC(多版本并发控制),实现事务的隔离性。

步骤4:更新内存数据,记录redo log(WAL技术核心)
记录完undo log后,InnoDB开始执行真正的更新操作,核心分为两步,这也是MySQLWAL技术(Write-Ahead Logging,预写日志)的核心逻辑:

先更新内存中的记录:修改buffer pool中id=1的记录的name字段,从‘zhangsan’改为‘xiaoming’,同时将这一页标记为脏页(脏页:内存中的数据和磁盘中的数据不一致);

再记录redo log(重做日志):将“更新操作”(比如“user表id=1的name从‘zhangsan’改为‘xiaoming’”)写入redo log buffer(redo log的内存缓存),此时更新操作就算“执行完成”,可以向客户端返回成功信息了。

这里有个非常关键的点:更新操作不会立即将脏页写入磁盘,而是先写redo log——因为磁盘I/O速度极慢,频繁写磁盘会严重影响性能;而redo log是顺序写入的,速度非常快,后续由InnoDB的后台线程(比如page cleaner线程),在空闲时将脏页异步写入磁盘,既保证了性能,又保证了数据安全。

如果MySQL突然断电,redo log buffer中的内容会丢失吗?答案:不会。因为redo log有“刷盘策略”(比如innodb_flush_log_at_trx_commit参数控制),默认情况下,会在事务提交时将redo log buffer中的内容刷入磁盘,保证即使断电,redo log中的记录也不会丢失,后续可以通过redo log恢复数据。

步骤5:记录binlog(用于主从复制、数据恢复)
InnoDB完成内存更新和redo log记录后,执行器会触发MySQL的binlog(二进制日志)记录操作——这里要注意,binlog是MySQL服务层的日志,不是InnoDB存储引擎的日志,所有存储引擎(比如MyISAM)都会使用binlog。具体细节:

binlog会记录这条update语句的“逻辑操作”(比如“更新user表id=1的name为xiaoming”),而不是物理数据的变化;

此时binlog不会直接刷新到磁盘的binlog文件中,而是先写入binlog cache(binlog的内存缓存);

binlog cache中的内容,会在“事务提交”时,统一刷新到磁盘的binlog文件中(避免频繁刷盘,提升性能)。

binlog的核心作用:主从复制(主库将binlog发送给从库,从库执行binlog中的操作,实现主从数据一致)、数据恢复(如果数据丢失,可以通过binlog重放操作,恢复数据)。

步骤6-8:两阶段提交(保证redo log和binlog一致)
这是整个更新流程中最复杂、也最关键的一步——为什么需要两阶段提交?因为redo log(InnoDB层)和binlog(服务层)是两个独立的日志,如果不做协调,可能会出现“redo log提交成功,但binlog提交失败”,或者反之,导致主从数据不一致、数据恢复失败。

两阶段提交(prepare阶段 + commit阶段)的核心目的,就是保证redo log和binlog的“原子性”,要么两者都提交成功,要么两者都失败,避免出现不一致的情况,具体步骤如下:

  • prepare阶段:InnoDB将redo log对应的事务状态设置为“prepare”(准备状态),然后将redo log buffer中的内容刷入磁盘(确保redo log不会丢失);

  • commit阶段:MySQL服务层将binlog cache中的内容刷入磁盘的binlog文件中,刷盘成功后,调用InnoDB的提交事务接口,将redo log的事务状态从“prepare”改为“commit”,并将该状态写入redo log文件(不需要立即刷盘,因为此时binlog已经刷盘,即使redo log的commit状态丢失,后续也能通过binlog判断事务是否成功);

  • 事务提交完成,InnoDB释放事务相关的资源,整个update语句执行完毕。

如果在两阶段提交过程中出现异常(比如断电),会怎么处理?

  • 如果是prepare阶段完成,commit阶段未完成:MySQL重启后,会检查binlog中是否有该事务的记录,如果有,就将redo log的状态改为commit;如果没有,就通过undo log回滚事务,保证redo log和binlog一致;

  • 如果是prepare阶段未完成:直接通过undo log回滚事务,不会影响数据一致性。

03核心总结

整体流程:连接器 → 跳过查询缓存(但清空对应表缓存) → 解析器 → 预处理器 → 优化器 → 执行器 → InnoDB(更新核心);

关键差异:和select语句相比,update不使用查询缓存但清空缓存、执行器后续会触发undo log、redo log、binlog和两阶段提交;

底层日志:undo log(回滚)、redo log(重做,WAL核心)、binlog(主从复制+数据恢复),三者缺一不可;

性能优化:buffer pool减少磁盘I/O、redo log和binlog先写内存再异步刷盘、两阶段提交保证数据一致性;

版本注意:MySQL 8.0移除查询缓存,无需考虑;InnoDB是唯一支持事务、redo log、undo log的存储引擎(MyISAM不支持)。

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

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

相关文章

STM32心率血氧手环(可报警)

目录硬件设计传感器技术软件算法应用场景开发资源源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式!硬件设计 STM32心率血氧手环通常基于STM32微控制器(如STM32F4或STM32L4系列),搭配光学传感器模块&am…

[langchain 内部数据传递层级]

@dynamic_prompt def dynamic_system_prompt(request: ModelRequest) -> str:user_name = request.runtime.context.user_name system_prompt = f"You are a helpful assistant. Address the user as {user_n…

STM32智能宠物喂食

目录 STM32智能宠物喂食系统概述核心功能硬件组成软件设计应用场景扩展功能 源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! STM32智能宠物喂食系统概述 STM32智能宠物喂食系统是一种基于STM32微控制器的自动化解决方案,通…

2026年选择敏捷咨询机构:从“工具应用”到“价值落地”的转型关键

在VUCA时代,企业对敏捷的需求早已超越Scrum会议、看板工具的表层应用,转向全价值链的效率提升与组织能力重塑。2026年,随着数字化转型进入深水区,敏捷咨询机构的核心价值不再是简单传授方法论,而是帮助企业破解“敏捷落…

2026年马年零食大礼盒推荐Top5:从年味到健康的“不踩雷”选型指南

2026年马年零食大礼盒推荐Top5:从年味到健康的“不踩雷”选型指南2026年马年春节临近,不少人已经进入“零食礼盒挑选关键期”——既要满足“贴春联、拜大年”的年味仪式感,又要兼顾老人怕甜、孩子爱脆、年轻人要健康…

论文降AI率必备!5款工具横向测评,到底哪款能帮你将AIGC率降低80%以上

上周答辩前夕,我室友差点崩溃——论文被导师退回来了,原因是"疑似大量使用AI生成内容"。她哭着说:"我明明自己改过好几遍啊,为什么还是被查出来了?" 这场景我太熟悉了。去年我自己也经历过&#…

Java计算机毕设之基于Java+springboot的隧道云视频监控管理信息平台设计与实现(完整前后端代码+说明文档+LW,调试定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

[Unreal shader]深度缓冲重建世界坐标

UE中通过深度缓冲重建世界空间坐标原理和Unity shader重建原理基本一致,但是UE中重建世界坐标的实现路径与Unity是不一致的 :• Unity中使用 SAMPLE_DEPTH_TEXTUR 采样的是原始深度值(RawDepth),是一个范围[0&#xff…

【毕业设计】基于springboot的隧道云视频监控管理信息平台设计与实现(源码+文档+远程调试,全bao定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

logging库使用教程

logging日志模块 logging是python常用的日志模块,logging涉及三个概念:logger可以理解为记者,决定写什么 handler可以理解为发布渠道,决定发到哪里 formatter可以理解为文章格式,决定排版格式 Level可以理解为重要…

【课程设计/毕业设计】基于springboot的隧道云视频监控管理信息平台设计与实现隧道内事故、火灾、车辆滞留等问题监察【附源码、数据库、万字文档】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

SpringBoot:封装 starter

01 Starter 核心机制 SpringBoot 核心思想是约定大于配置,而 Starter 正是这一思想的核心落地载体。 简单来说,Starter 把某一类功能的依赖管理、默认配置、自动装配逻辑打包成一个独立 Jar 包。 项目只需引入这个 Jar 包,就能直接使用对应功…

滴滴 wsgsig secdd-challenge

声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由 此产生的一切后果均与作者无关! 部分python代码 url "ota/re…

RabbitMQ 在大数据领域的故障排查与解决方案

RabbitMQ 在大数据领域的故障排查与解决方案 关键词:RabbitMQ、大数据、消息队列、故障排查、性能优化、高可用性、消息丢失 摘要:本文深入探讨RabbitMQ在大数据环境下的常见故障及其解决方案。我们将从RabbitMQ的核心架构出发,分析其在大数据场景下面临的挑战,详细介绍故障…

Linux 内核漏洞提权

一、 内核提权的核心原理Linux 采用权限分级机制(root:0,普通用户:1-65535),内核运行在最高权限的内核态(Ring 0),用户程序运行在用户态(Ring 3)。内核提权的…

连接 AI 的隐形纽带:深度解构 MCP 传输层——从 Stdio 到 SSE 的实战抉择与架构差异

文章目录 🛰️ 连接 AI 的隐形纽带:深度解构 MCP 传输层——从 Stdio 到 SSE 的实战抉择与架构差异 📡🏗️ 第一章:协议与通道的解耦——MCP 通信的底层逻辑1.1 JSON-RPC 2.0:MCP 的通用语言1.2 传输层的两…

计算机毕业设计springboot基于农科所农作物信息管理系统的设计与实现 基于SpringBoot的农业科研院所作物数据智慧管理平台的设计与实现面向农科机构的SpringBoot作物全生命周期

计算机毕业设计springboot基于农科所农作物信息管理系统的设计与实现8h3n8w22 (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。在“互联网农业”快速渗透的今天,农科所…

测试转网络安全如何弯道超车?

目录😭 测试的痛,谁懂?1. 重复劳动,永无止境2. 被动等待,毫无主动权3. 技术含量低,成长受限❓ 转行网安1. 测试经验,天然就是安全优势2. 技能高度重叠,转型零成本3. 工作模式更自由&…

Java计算机毕设之基于springboot的智慧医疗网上预约系统智慧医疗服务-智慧医疗服务平台(完整前后端代码+说明文档+LW,调试定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

微服务架构演进实战 从单体到微服务的拆分原则与DDD入门

目录 💡 先说说我经历的微服务"车祸现场" ✨ 摘要 1. 为什么需要从单体转向微服务? 1.1 单体的痛苦现实 1.2 微服务的核心优势 2. 领域驱动设计(DDD)核心概念 2.1 战略设计:划分业务边界 2.2 战术设…