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:加瓦点灯, 每天推送干货知识!

相关推荐
意倾城17 分钟前
Spring Boot 配置文件敏感信息加密:Jasypt 实战
java·spring boot·后端
火皇40518 分钟前
Spring Boot 使用 OSHI 实现系统运行状态监控接口
java·spring boot·后端
薯条不要番茄酱1 小时前
【SpringBoot】从零开始全面解析Spring MVC (一)
java·spring boot·后端
懵逼的小黑子8 小时前
Django 项目的 models 目录中,__init__.py 文件的作用
后端·python·django
小林学习编程10 小时前
SpringBoot校园失物招领信息平台
java·spring boot·后端
java1234_小锋12 小时前
Spring Bean有哪几种配置方式?
java·后端·spring
柯南二号13 小时前
【后端】SpringBoot用CORS解决无法跨域访问的问题
java·spring boot·后端
每天一个秃顶小技巧13 小时前
02.Golang 切片(slice)源码分析(一、定义与基础操作实现)
开发语言·后端·python·golang
gCode Teacher 格码致知14 小时前
《Asp.net Mvc 网站开发》复习试题
后端·asp.net·mvc
Moshow郑锴16 小时前
Spring Boot 3 + Undertow 服务器优化配置
服务器·spring boot·后端