MySQL更新语句执行全流程:从Buffer Pool修改到二阶段提交

文章目录

  • 前言
  • 一条SQL更新语句是如何执行的?
    • [第一阶段:Server 层的准备与查找阶段](#第一阶段:Server 层的准备与查找阶段)
      • [1. 连接器与分析器:](#1. 连接器与分析器:)
      • [2. 优化器与执行器:](#2. 优化器与执行器:)
    • [第二阶段:InnoDB 引擎的内存与日志操作(真正开始改数据)](#第二阶段:InnoDB 引擎的内存与日志操作(真正开始改数据))
      • [1. 引擎搜寻与加载数据(Buffer Pool 机制):](#1. 引擎搜寻与加载数据(Buffer Pool 机制):)
      • [2. 记录回滚日志(undo log):](#2. 记录回滚日志(undo log):)
      • [3. 在内存中更新数据:](#3. 在内存中更新数据:)
    • 第三阶段:核心"二阶段提交"与日志落盘
      • [1. 写入 redo log --- Prepare 阶段(第一阶段)](#1. 写入 redo log — Prepare 阶段(第一阶段))
      • [2. 写入 binlog --- 提交阶段(第二阶段 A)](#2. 写入 binlog — 提交阶段(第二阶段 A))
      • [3. 修改 redo log 状态 --- Commit 阶段(第二阶段 B)](#3. 修改 redo log 状态 — Commit 阶段(第二阶段 B))
  • 结语

前言

更新语句的执行远比查询复杂。它不仅要在内存中修改数据,还要在崩溃时保证数据不丢、在主从之间保持一致。理解这条涉及undo log、redo log与binlog的写入链路,是你掌握MySQL事务与数据安全机制的必经之路。

一条SQL更新语句是如何执行的?

接下来我将以UPDATE user SET name = '李四' WHERE id = 10;这行SQL更新语句来解释执行过程

第一阶段:Server 层的准备与查找阶段

1. 连接器与分析器:

  • 客户端发送更新语句。连接器首先进行权限校验。
  • 分析器进行词法和语法分析,识别出这是一条 UPDATE 语句,要更新 user 表中 id = 10 的行。

2. 优化器与执行器:

  • 优化器决定使用 id 的主键索引,并生成执行计划。
  • 执行器负责指挥存储引擎。但在修改数据之前,执行器必须先拿到这行数据。
  • 执行器调用 InnoDB 引擎接口:"帮我把 id = 10 这一行的数据取出来"。

第二阶段:InnoDB 引擎的内存与日志操作(真正开始改数据)

1. 引擎搜寻与加载数据(Buffer Pool 机制):

  • InnoDB 收到请求后,先去内存的 Buffer Pool(缓冲池) 中查找是否存在 id = 10 所在的数据页。
  • 如果在内存中,直接读出准备修改;如果不在内存中,引擎会先从磁盘将该数据页读入到 Buffer Pool 中。

2. 记录回滚日志(undo log):

  • 在内存中准备修改数据之前,InnoDB 会先将这一行原先的值(比如 name = '张三')记录到 undo log 中。
  • 底层作用:undo log 是为了实现事务的原子性(A)。如果后续事务因为某种原因回滚(Rollback),或者程序崩溃,数据库需要利用 undo log 把数据恢复成原本的模样。

3. 在内存中更新数据:

  • 记录完 undo log 后,InnoDB 引擎正式在内存(Buffer Pool)中执行修改,将 name 的值改为 '李四'
  • 注意:此时,磁盘上的数据文件还没有被修改,内存中的这个数据页与磁盘上的不一致,变成了"脏页(Dirty Page)"。MySQL 并不是每执行一条更新就立刻写一次磁盘,因为随机磁盘 I/O 极其缓慢,它会等待后台线程异步将脏页刷新(Flush)到磁盘。

第三阶段:核心"二阶段提交"与日志落盘

为了防止由于内存更新了、磁盘没更新时突然断电导致数据丢失,以及为了保证主从库数据的一致性,接下来的日志写入将严格遵循二阶段提交(Two-Phase Commit):

1. 写入 redo log --- Prepare 阶段(第一阶段)

  • InnoDB 引擎将"在某个数据页的某个偏移量上把 name 改为了李四"这一物理变动记录到 redo log(重做日志)中。
  • 此时,将该事务在 redo log 中的状态标记为 prepare(准备阶段)。
  • 接着,把 redo log 对应的内存数据强行刷新到磁盘上(由 innodb_flush_log_at_trx_commit 参数控制)。
  • 引擎向执行器汇报:"我这边已经写好物理日志并进入准备状态了,你可以写 binlog 了"。

2. 写入 binlog --- 提交阶段(第二阶段 A)

  • 执行器收到引擎的通知后,开始生成这一条操作的 binlog(逻辑日志,记录的是具体的 SQL 语句或行变化数据,如"将 id=10 的 name 改为李四")。
  • 执行器将 binlog 写入到 Server 层的 binlog 文件中,并强行刷新到磁盘(由 sync_binlog 参数控制)。

3. 修改 redo log 状态 --- Commit 阶段(第二阶段 B)

  • binlog 写入成功后,执行器调用引擎的事务提交接口。
  • InnoDB 引擎把刚刚在 redo log 中该事务的状态从 prepare 改为 commit(提交状态)
  • 至此,整个更新事务宣告成功结束,执行器向客户端返回"更新成功"。

结语

每一次UPDATE背后,都是内存、磁盘与日志的精密协作。undo log守护回滚,redo log抵御崩溃,binlog维系主从,二阶段提交则将三者拧成一股绳。懂了这条链路,你才真正懂了MySQL的数据安全。

相关推荐
颂love3 小时前
MySQL的执行流程
android·数据库·mysql
海市公约3 小时前
一条SQL查询的完整旅程:MySQL执行流程深度解析
sql·mysql·数据库优化·执行计划·连接器·查询缓存·sql执行原理
程序leo源3 小时前
Qt窗口详解
开发语言·数据库·c++·qt·青少年编程·c#
这个DBA有点耶3 小时前
COUNT进阶:超大表的近似计数与HyperLogLog
数据库·sql·程序人生·学习方法·dba·改行学it
武子康3 小时前
调查研究-138 全球机器人产业深度调研报告【01 篇】:市场规模、竞争格局与商业化成熟 2026
服务器·数据库·ai·chatgpt·机器人·具身智能
zhojiew3 小时前
在本地PostgreSQL使用pgvector构建生成式 AI 应用的实践
数据库·人工智能·postgresql
Yushan Bai4 小时前
EXADATA X5数据库一体机节点login: failure forking: Cannot allocate memory问题处理
数据库·oracle·vr
KaMeidebaby4 小时前
卡梅德生物技术快报|噬菌体肽库展示技术构建 Mhp168‑Hsp70 定向随机肽库:流程、质控与数据结果
前端·数据库·其他·百度·新浪微博
沪漂阿龙4 小时前
MySQL 面试题爆款详解:InnoDB 页机制、B+树索引、Buffer Pool、Redo Log、页分裂与性能优化一次讲透
b树·mysql·性能优化