回答
更新 SQL 的执行过程与查询数据的流程类似。
如update t_user set age = 10 where id = 12
的执行过程如下(存储引擎默认为 InnoDB):
1、客户端:客户端基于网络连接到 MySQL 服务器,发送更新 SQL 语句到服务器。
2、Server 层:
- Server 层接收到更新请求后,分析器通过词法分析和语法分析生成语法分析树知道这是条更新语句。
- 优化器基于语法树(AST)选择合适的索引生成执行计划,如上述 SQL 会使用 ID 这个索引。
- 执行器根据执行计划调用存储引擎 API 先找到这一行数据,再更新对应字段。
- 执行器生成更新操作的 Bin Log,并把 Bin Log 写入磁盘(备注:此处执行器记录 Bin Log 操作是在存储引擎层写入 Redo Log 且事务处于 Prepare 阶段未 Commit 之时,具体可参考下图)。
3、存储引擎层:
- 读取数据页,存储引擎会先从 Buffer Pool 获取更新数据(此处为 id = 2 这条记录)所在数据页,如果没有则从磁盘中读入 Buffer Pool。
- 开启事务,记录 Undo Log,将其写入 Buffer Pool 的 Undo Page
- Prepare 阶段,更新数据页中的记录,被修改的数据页称为脏页。修改时会记录 Redo Log,将其写入 Log Buffer,再刷盘到磁盘的 Redo Log 日志文件,此时事务状态为 Prepare 阶段。
- 通知 Server 层,存储引擎层通知 Server 层提交数据(此时 Server 层执行器先记录 Bin Log Cache,事务提交时再将 Bin Log 刷新到磁盘)。
- Commit 阶段,存储引擎将 Redo Log 的事务状态标记为 Commit。
扩展
SQL 更新执行流程
SQL 更新为什么是两阶段提交?
上述更新流程 redo log 写入过程拆分为两个步骤:Prepare 和 Commit,这就是两阶段提交。
redo log
redo log 是 InnoDB 引擎特有的,用于保证 crash-safe 能力。即当 MySQL 在任何时刻突然奔溃,重启后数据也不会丢失。其记录的是“在某个数据页上做了什么修改”。
binlog
binlog 是 Server 层的日志,称为归档日志。其记录 SQL 语句的原始逻辑,如上述更新语句的“给 id = 12 这一行的 age 字段赋值为10”。而且 binlog 是追加写入,当 binlog 文件写到一定大小后会切换为下一个文件,不会覆盖之前的日志。
数据一致性
在 Innodb 引擎中,redo log 和 binlog 写入时采用 prepare 和 commit 两阶段方式,是为了保证数据一致性。可以想象下如果采用两个日志直接提交的方式,无论谁先谁后,在数据库宕机重启后都会出现数据不一致。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。