MySQL笔记 | 一条更新语句是如何执行的?

笔记哥 / 04-01 / 39点赞 / 0评论 / 284阅读
## 1. 更新语句的“出生”:从你敲下回车键开始 想象一下,你正在电脑前敲代码,突然灵光一闪,写了一条更新语句,比如: ```csharp UPDATE users SET age = 20 WHERE id = 1; ``` 你按下回车键,这条更新语句就像一颗刚刚发射的火箭,准备进入 MySQL 的“宇宙”中执行。那么,接下来会发生什么呢? 先贴个流程图,看一下整体流程: ![](https://cdn.res.knowhub.vip/c/2504/01/0308755a?G50AAGRBz%2fMr7OkqmFEpEEV41bO25fm8PgQUPZ06%2bCO3K%2fRIf3ZUX88zuvd81u8YM42gg35ziV4zvVnzK%2biNe4gV0H1e6xz6Edrz245upb6LSt2Etu856GLC3pQr6O2hoy3%2be3jNBuOwRHJZHytr7GwiRxkKUz%2ffejo95et5%2fs9rul9Ocnu9nh4z) ## 2. 更新语句的“第一站”:连接器 和查询语句一样,更新语句的第一站也是 连接器。连接器就像是一个门卫大叔,负责检查你的身份。它会验证你的用户名和密码,看看你是不是有权限进入这个数据库。 **验证身份:**连接器会检查你的用户名和密码是否正确。如果不对,它会直接把你拒之门外,就像你去参加一个高端派对,结果发现邀请函是假的,门卫大叔会毫不留情地把你拦在外面。 **权限检查:**如果你通过了身份验证,连接器还会检查你有没有执行这条更新语句的权限。比如,你想更新 users 表,但你只有读取 orders 表的权限,那连接器会告诉你:“不好意思,你没有权限更新这个表,哪儿凉快哪儿待着去吧!” 如果一切顺利,连接器会为你建立一个连接,并且这个连接会一直保持,直到你主动断开或者超时。这个连接就像是你和 MySQL 之间的“电话线”,随时可以通话。 ## 3. 更新语句的“第二站”:分析器 通过了连接器的检查,更新语句接下来会来到 分析器。分析器就像是一个“语法老师”,它会检查你的 SQL 语句是否符合语法规则。 **词法分析:**分析器首先会进行词法分析,把 SQL 语句拆分成一个个的“单词”。比如,`UPDATE`、`users`、`SET`、`age`、`=`、`20`、`WHERE`、`id`、`=`、`1`,这些都会被识别为不同的“单词”。 **语法分析:**接下来,分析器会进行语法分析,检查这些“单词”是否符合 SQL 的语法规则。比如,UPDATE 后面必须跟着表名,SET 后面必须跟着字段和值,WHERE 后面必须跟着条件等等。如果语法有问题,分析器会直接报错,就像是你写作文时,老师发现你句子不通顺,直接给你打个大红叉。 如果更新语句通过了分析器的检查,MySQL 就会生成一个“语法树”,这个树结构就像是 SQL 语句的“骨架”,后续的执行过程都会基于这个骨架进行。 ## 4. 更新语句的“第三站”:优化器 通过了分析器的检查,更新语句接下来会来到 优化器。优化器就像是一个“聪明的管家”,它会根据 SQL 语句的“骨架”,决定如何执行这条更新语句才是最有效率的。 **选择执行计划**:优化器会考虑多种执行方案,比如使用哪个索引、如何定位要更新的记录等等。它会根据表的统计信息、索引的情况,选择出一个最优的执行计划。这就像是你在做旅行计划时,优化器会帮你选择最省时间、最省钱的路线。 **索引选择**:如果你的更新语句中有 WHERE 条件,优化器会决定是否使用索引来加速查询。比如,id = 1 这个条件,如果 id 字段上有索引,优化器可能会选择使用索引来快速定位要更新的记录。 优化器的目标是让更新语句执行得更快、更省资源。不过,优化器也不是万能的,有时候它也会做出错误的决定。这时候,你可能需要手动干预,比如通过 FORCE INDEX 来强制使用某个索引。 ## 5. 更新语句的“第四站”:执行器 经过了优化器的“精心策划”,更新语句终于来到了 执行器。执行器就像是一个“实干家”,它会根据优化器生成的执行计划,真正地去执行这条更新语句。 ### 5.1 调用存储引擎 执行器首先会调用存储引擎的接口,准备读取数据。MySQL 的存储引擎有很多种,比如 InnoDB、MyISAM 等,执行器会根据表的存储引擎类型,调用相应的接口。 ### 5.2 读取要更新的数据 执行器会根据优化器选择的执行计划,定位到要更新的记录。比如,id = 1 这个条件,执行器会先找到 id 为 1 的记录,然后再进行更新。 ### 5.3 写入更新日志(Undo Log) 在真正更新数据之前,MySQL 会先将旧数据写入 Undo Log(回滚日志)。Undo Log 的作用是记录数据更新前的状态,以便在事务回滚时能够恢复到更新前的状态。这就像是你在玩游戏时,系统会自动保存一个存档,万一你玩砸了,还可以回档重来。 ### 5.4 更新数据 接下来,执行器会真正地更新数据。比如,将 age 字段的值从原来的值更新为 20。 ### 5.5 写入重做日志(Redo Log) 在更新数据的同时,MySQL 还会将更新操作写入 Redo Log(重做日志)。Redo Log 的作用是记录数据的修改操作,以便在数据库崩溃时能够恢复数据。这就像是你在写作业时,先用铅笔写一遍,再用钢笔描一遍,万一铅笔写的被擦掉了,钢笔写的还能保留。 ### 5.6 写入Binlog(二进制日志) 如果开启了 Binlog,MySQL 还会将更新操作写入 Binlog。Binlog 的作用是记录所有的数据修改操作,以便在主从复制或数据恢复时使用。这就像是你在写日记,记录下每天发生的事情,方便以后回顾。 ## 6. 更新语句的“第五站”:提交事务 如果更新语句是在一个事务中执行的,那么在执行完更新操作后,MySQL 还需要进行 事务提交。 ### 6.1 提交Redo Log 在事务提交时,MySQL 会先将 Redo Log 写入磁盘,确保更新操作已经持久化。这就像是你在考试时,先把答案写在答题卡上,确保不会因为时间不够而丢分。 ### 6.2 提交Binlog 接下来,MySQL 会提交 Binlog,确保所有的数据修改操作都已经记录。这就像是你在写日记时,把今天的日记写完并保存。 ### 6.3 释放锁 最后,MySQL 会释放事务中占用的锁资源,允许其他事务继续操作数据。这就像是你在图书馆借书时,看完书后把书还回去,其他人才能继续借阅。 ## 7. 更新语句的“终点站”:返回结果 经过了连接器、分析器、优化器、执行器、事务提交这一系列的“关卡”,更新语句终于执行完毕,结果也返回给了你。这时候,你可以看到更新操作的影响行数,比如: ```csharp Query OK, 1 row affected (0.02 sec) ``` 这表示更新操作成功,影响了 1 行数据。 ## 8. 总结:更新语句的“奇幻之旅” 好了,咱们来总结一下更新语句在 MySQL 中的执行过程: **连接器**:验证你的身份和权限,建立连接。 **分析器**:检查 SQL 语句的语法是否正确,生成语法树。 **优化器**:选择最优的执行计划,决定如何使用索引、如何定位要更新的记录等。 **执行器**: - 调用存储引擎的接口,读取要更新的数据。 - 写入 Undo Log,记录更新前的状态。 - 更新数据。 - 写入 Redo Log,确保更新操作持久化。 - 写入 Binlog,记录数据修改操作。 **事务提交**: - 提交 Redo Log。 - 提交 Binlog。 - 释放锁资源。 **返回结果**:返回更新操作的影响行数。 这个过程就像是一场“奇幻之旅”,更新语句从你手中出发,经过层层关卡,最终完成了数据的更新。虽然过程复杂,但 MySQL 的每个组件都各司其职,确保更新语句能够高效、准确地执行。 ## 9. 总结 事务的重要性:更新语句通常是在事务中执行的,事务的 ACID 特性(原子性、一致性、隔离性、持久性)确保了数据的安全性和一致性。 锁机制:在更新数据时,MySQL 会对要更新的记录加锁,防止其他事务同时修改同一条记录。这就像是你在图书馆借书时,先把书拿到手,其他人就不能再借这本书了。 日志的作用:Undo Log、Redo Log 和 Binlog 是 MySQL 中非常重要的日志,它们分别用于事务回滚、崩溃恢复和数据复制。