SQL语句是怎么被执行的?一条sql语句的幕后旅程

通过一条 UPDATE 语句,搞懂mysql的幕后


引言

你可能每天都在写 SQL,但是否真正了解,一条 UPDATE 语句在 MySQL 中经历了哪些阶段,哪些日志在为你的事务保驾护航,哪些机制在悄悄保障着数据一致性?

今天我们通过一个简单的更新操作,带你从执行器到磁盘,深入理解 MySQL 的底层机制


0. SQL 语句

sql 复制代码
UPDATE user SET age = 16 WHERE id = 1;

目标很明确:把 user 表中 id = 1 的那行记录的 age 字段更新为 16


1. SQL 进入 MySQL 后,发生了什么?

第一步:连接层处理

  • 客户端发来 SQL,进入 连接层,MySQL 验证权限并分配线程。

第二步:SQL 层解析与优化

  • 解析器将 SQL 字符串转换为语法树。
  • 预处理器校验表、字段是否存在。
  • 优化器选择最优的执行路径(一般是走主键索引)。
  • 执行器准备执行具体操作。

2. 执行器找存储引擎"办事":InnoDB 来了

MySQL 使用 InnoDB 存储引擎时,数据存储、事务和日志控制都在它手上完成。


3. 开始执行:InnoDB 的详细执行流程

下面我们进入"时间线"视角,来看 InnoDB 是如何一步步处理这条语句的:

🧭 3.1 查询数据页

  • 根据主键 id = 1,从 Buffer Pool(缓冲池) 查找对应的数据页。
  • 如果命中,直接操作;否则从磁盘读取页,加载到 Buffer Pool。

✅ Buffer Pool 是内存中的数据页缓存,避免频繁磁盘读写。


🪓 3.2 生成 undo log(撤销日志)

  • 假设原来该行的 age = 18
  • InnoDB 会先生成一条 undo log
text 复制代码
undo log: update user set age = 18 where id = 1;
  • 写入 undo log buffer ,后续会刷入磁盘的 undo tablespace
  • 用于事务回滚或 MVCC 快照读。

🔧 3.3 修改 Buffer Pool 中的数据页

  • 将 age 字段更新为 16,但只是修改内存数据页,并未写入磁盘!

🔁 3.4 生成 redo log(重做日志)

  • 为了防止崩溃丢失,写入一条物理层的变更日志,记录:
text 复制代码
redo log: 页号 XX 中的 offset XX 的 age 字段值从 18 → 16
  • Redo log 被写入 redo log buffer,准备刷盘。

4. 事务日志提交:两阶段提交登场

InnoDB 的核心保障:原子性和崩溃恢复,靠 redo log 和 binlog 联手完成。

🚩 4.1 prepare 阶段

  • 将 redo log 刷入磁盘(ib_logfile 文件),状态为 prepare

✍️ 4.2 写入 binlog(二进制日志)

  • MySQL Server 层生成 binlog(逻辑 SQL):
text 复制代码
binlog: update user set age = 16 where id = 1;
  • 写入 binlog buffer,刷入磁盘。

✅ 4.3 commit 阶段

  • InnoDB 标记 redo log 状态为 commit
  • 事务正式提交,客户端收到"更新成功"响应。

❗如果在 commit 前宕机,可以用 redo log 恢复;如果写 binlog 后崩溃但 redo log 未 commit,MySQL 会回滚事务,保持一致性。


5. 三种日志作用对比

日志类型 记录内容 写入时机 应用场景 属于哪一层
undo log 数据修改前的旧值 修改数据之前 回滚、MVCC 快照读 InnoDB
redo log 数据页的物理变更 修改之后(prepare) 崩溃恢复 InnoDB
binlog SQL 的逻辑变更 提交事务时 主从复制、增量备份 Server 层

6. 多操作事务如何保证原子性?

假设你有如下事务:

sql 复制代码
START TRANSACTION;
UPDATE user SET age = 16 WHERE id = 1;
UPDATE user SET name = 'Tom' WHERE id = 1;
COMMIT;
  • 所有修改都在同一个事务 ID 下。
  • 每条语句都生成自己的 undo log、redo log。
  • COMMIT 时,统一写入 binlog 和 redo commit。
  • 任何一个操作失败或中断,全部回滚 ------ 原子性保障!

7. 整体流程图(逻辑顺序)

perl 复制代码
客户端
  ↓
SQL 解析、优化
  ↓
执行器调用 InnoDB
  ↓
查 Buffer Pool(命中 or 加载磁盘页)
  ↓
生成 undo log
  ↓
更新 Buffer Pool 中数据
  ↓
写 redo log(prepare)
  ↓
写 binlog
  ↓
redo log commit → 事务提交

详细图如下:


8. 结语

虽然只是简单更新一个字段,但背后 MySQL 做了大量精密工作------从内存控制、日志写入到事务保障,处处体现出设计者的匠心。


最后

如果文章对你有帮助,点个免费的赞鼓励一下吧!关注gzh:加瓦点灯, 每天推送干货知识!

相关推荐
WeiXiao_Hyy16 分钟前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
苏渡苇22 分钟前
优雅应对异常,从“try-catch堆砌”到“设计驱动”
java·后端·设计模式·学习方法·责任链模式
long31634 分钟前
Aho-Corasick 模式搜索算法
java·数据结构·spring boot·后端·算法·排序算法
rannn_1111 小时前
【苍穹外卖|Day4】套餐页面开发(新增套餐、分页查询、删除套餐、修改套餐、起售停售)
java·spring boot·后端·学习
短剑重铸之日1 小时前
《设计模式》第十一篇:总结
java·后端·设计模式·总结
Dragon Wu2 小时前
Spring Security Oauth2.1 授权码模式实现前后端分离的方案
java·spring boot·后端·spring cloud·springboot·springcloud
一个有梦有戏的人2 小时前
Python3基础:进阶基础,筑牢编程底层能力
后端·python
爬山算法3 小时前
Hibernate(88)如何在负载测试中使用Hibernate?
java·后端·hibernate
独断万古他化3 小时前
【Spring 原理】Bean 的作用域与生命周期
java·后端·spring
我爱加班、、3 小时前
Websocket能携带token过去后端吗
前端·后端·websocket