Innodb一次更新动作

这个过程拆解为 "准备阶段"、"执行阶段"、"提交阶段(核心)" 和 "后台阶段" 四个部分。

假设执行 SQL:UPDATE user SET name = 'Li' WHERE id = 1;(原值为 'Wang')

第一阶段:准备与加载 (Buffer Pool)

连接器与解析:

MySQL Server 层收到 SQL,进行解析和权限校验。

执行器调用引擎:

执行器向 InnoDB 引擎索要 id=1 这一行数据。

加载到内存 (Buffer Pool):

InnoDB 检查 Buffer Pool(内存缓冲池)里有没有这就数据页。

如果有:直接返回。

如果没有:从磁盘(.ibd文件)加载该页到 Buffer Pool 中。

第二阶段:执行与日志记录 (Undo & Memory)

这是事务开始真正干活的阶段,所有操作都在内存中完成,还没碰磁盘数据文件。

写入 Undo Log (后悔药):

在修改数据前,InnoDB 会先把旧值('Wang')写入 Undo Log。

作用:如果事务失败回滚,或者通过 MVCC 进行快照读,需要靠它找回旧值。

更新内存 (Dirty Page):

在 Buffer Pool 中,将 id=1 的 name 修改为 'Li'。

此时,内存里的数据是新的,但磁盘上的数据还是旧的。这页数据被称为 "脏页" (Dirty Page)。

写入 Redo Log Buffer (崩溃恢复):

将这次物理修改("在第xx页第xx偏移量做了什么修改")写入内存中的 Redo Log Buffer。

注意:此时 Redo Log 还在内存里,还没落盘。

第三阶段:提交事务 (Commit & 2PC) ------ 最关键

当客户端发起 COMMIT 时,为了保证 Redo Log(引擎层) 和 Binlog(Server层) 的一致性,MySQL 使用了 两阶段提交 (Two-Phase Commit, 2PC)。

Redo Log 刷盘 (Prepare 状态):

InnoDB 将 Redo Log Buffer 里的内容写入磁盘的 Redo Log 文件中,并将状态标记为 PREPARE。

作用:也就是常说的 WAL(Write-Ahead Logging),先写日志,再写数据。只要 Redo Log 在,数据库宕机重启就能恢复数据。

写入 Binlog (归档):

MySQL Server 层将该操作的逻辑日志(SQL语句或行变更记录)写入磁盘的 Binlog 文件。

作用:用于主从复制和数据恢复。

Redo Log 提交 (Commit 状态):

InnoDB 收到 Binlog 写成功的通知后,再次操作 Redo Log,将状态改为 COMMIT。

至此,事务才算真正成功。

第四阶段:后台刷盘 (Checkpoint)

脏页刷盘:

此时,id=1 的数据在磁盘的数据文件(.ibd)里依然是旧值 'Wang'。

MySQL 的后台线程(Master Thread)会在系统空闲或内存不够时,将 Buffer Pool 中的 脏页 慢慢刷回到磁盘数据文件中。

这个过程叫 Checkpoint。

markup 复制代码
[用户] UPDATE ... -> [Server层]
      |
      v
[InnoDB] 1. 加载数据页到 Buffer Pool
      |
      v
[InnoDB] 2. 写旧值到 Undo Log (为了回滚)
      |
      v
[InnoDB] 3. 更新 Buffer Pool 中的内存数据 (变成脏页)
      |
      v
[InnoDB] 4. 写新值到 Redo Log Buffer (内存)
      |
      v
[用户] COMMIT;
      |
      v
------------------ 两阶段提交 (2PC) 开始 ------------------
[InnoDB] 5. Redo Log 刷盘 (状态: PREPARE)  <-- 崩溃恢复保障
      |
[Server] 6. Binlog 刷盘                    <-- 主从复制保障
      |
[InnoDB] 7. Redo Log 更新 (状态: COMMIT)
------------------ 两阶段提交 (2PC) 结束 ------------------
      |
      v
[后台线程] 8. 慢慢把 Buffer Pool 的脏页刷到磁盘 (.ibd文件)

面试官可能会追问的深层问题:

Q1: 为什么要两阶段提交(2PC)?

回答:为了防止 Redo Log 和 Binlog 不一致。

如果先写 Redo Log 成功,Binlog 失败:主库重启后通过 Redo Log 恢复了数据,但 Binlog 里没这条数据,导致从库(备库)丢数据。

如果先写 Binlog 成功,Redo Log 失败:主库宕机重启后数据丢了,但从库通过 Binlog 同步了数据,导致主从不一致。

2PC 保证了要么两个都成功,要么都失败。

Q2: 既然 Redo Log 已经写磁盘了,为什么不直接把数据写到磁盘(.ibd)?

回答:这是为了性能。

写数据文件(.ibd)是随机写(Random I/O),因为数据分布在磁盘的不同位置,速度慢。

写 Redo Log 是顺序写(Sequential I/O),是追加写入,速度极快。

这就是 WAL (Write-Ahead Logging) 的核心思想:用顺序写代替随机写,提升并发能力。

Q3: 如果事务提交后,脏页还没刷盘,数据库宕机了怎么办?

回答:不用担心。重启时,InnoDB 会读取磁盘上的 Redo Log,把没刷盘的修改重新应用(Replay)到内存中,恢复出宕机前的数据状态。

相关推荐
xcLeigh2 小时前
Python 项目实战:用 Flask 实现 MySQL 数据库增删改查 API
数据库·python·mysql·flask·教程·python3
Fleshy数模3 小时前
MySQL 表创建全攻略:Navicat 图形化与 Xshell 命令行双模式实践
linux·mysql
Nandeska3 小时前
15、基于MySQL的组复制
数据库·mysql
AllData公司负责人4 小时前
AllData数据中台-数据同步平台【Seatunnel-Web】整库同步MySQL同步Doris能力演示
大数据·数据库·mysql·开源
醇氧4 小时前
【docker】mysql 8 的健康检查(Health Check)
mysql·docker·容器
lekami_兰5 小时前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
爱学英语的程序员7 小时前
面试官:你了解过哪些数据库?
java·数据库·spring boot·sql·mysql·mybatis
·云扬·8 小时前
MySQL Redo Log落盘机制深度解析
数据库·mysql
码界筑梦坊8 小时前
330-基于Python的社交媒体舆情监控系统
python·mysql·信息可视化·数据分析·django·毕业设计·echarts