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

相关推荐
钡铼技术ARM工业边缘计算机25 分钟前
【成本降40%·性能翻倍】RK3588边缘控制器在安防联动系统的升级路径
后端
CryptoPP1 小时前
使用WebSocket实时获取印度股票数据源(无调用次数限制)实战
后端·python·websocket·网络协议·区块链
白宇横流学长1 小时前
基于SpringBoot实现的大创管理系统设计与实现【源码+文档】
java·spring boot·后端
草捏子2 小时前
状态机设计:比if-else优雅100倍的设计
后端
考虑考虑3 小时前
Springboot3.5.x结构化日志新属性
spring boot·后端·spring
涡能增压发动积3 小时前
一起来学 Langgraph [第三节]
后端
sky_ph3 小时前
JAVA-GC浅析(二)G1(Garbage First)回收器
java·后端
涡能增压发动积3 小时前
一起来学 Langgraph [第二节]
后端
hello早上好4 小时前
Spring不同类型的ApplicationContext的创建方式
java·后端·架构
roman_日积跬步-终至千里4 小时前
【Go语言基础【20】】Go的包与工程
开发语言·后端·golang