author
type
status
date
slug
summary
tags
category
icon
password
1.客户端发送 SQL → MySQL Server 层接收
客户端通过连接器与 MySQL 建立连接,发送 SQL。
2.Server 层:解析与优化阶段
(1)Parser(解析器)
- 词法分析:把 SQL 拆成 token
- 语法分析:生成解析树(Parse Tree)
(2)Optimizer(优化器)
- 选择最佳索引(基于统计信息)
- 决定 join 顺序
- 生成执行计划(Execution Plan)
执行计划交给 执行器(Executor)。
3.执行器(Executor)调度引擎(InnoDB)执行
(1) 执行器先告诉 InnoDB:
我要对 id=1 的记录执行 UPDATE,请你给我记录。
(2) InnoDB 检查 Buffer Pool
- 如果该页在内存:直接读取
- 不在:从磁盘加载到 Buffer Pool(数据页)
4.进入 InnoDB:读写前先加锁(行锁)
InnoDB 根据执行器的条件:
- 找到 id=1 对应的数据行
- 加 row lock(记录锁)
如果出现锁冲突,这里会阻塞。
5.产生 undo log(保证回滚 & MVCC)
在真正更新前,InnoDB 为这行数据创建:
Undo Log(回滚日志)
格式包含:
- 修改前旧值(如 age=18)
- 事务 ID
- 指向历史版本的指针(用于 MVCC)
作用:
- 事务回滚时可恢复旧数据
- 支持 MVCC 隔离级别(读到事务前版本)
undo log 写入 Buffer Pool 的 undo log segment(并非立即刷盘)。
6.修改 Buffer Pool 中的数据页(不是立刻写回磁盘)
InnoDB 在内存中更新页:
此时数据页处于 dirty page(脏页) 状态。
7.生成 redo log(WAL 机制)
为了保证 crash 后能恢复,InnoDB 为本次修改生成:
Redo Log(重做日志)
内容包括:
- 表空间号、页号
- 页的偏移量
- 修改的值
写入顺序:
此时状态是:
redo log 是采用 WAL(Write-Ahead Logging):
先保证 redo log 落盘,再允许提交事务
8.写入 binlog(Server 层)
事务执行到提交时,Server 层将本次执行写入:
Binlog(归档日志)
- 逻辑日志(如 statement/row 格式)
- 用于主从复制 & Point-in-Time Recovery
写入顺序:
9.两阶段提交(2PC)协调 binlog 与 redo log
为了保证 主从一致性:
MySQL 用两阶段提交保证 redo log 与 binlog 在 crash 时一致。
流程:
阶段一:prepare
InnoDB:
- 写 redo log(prepare 状态)
- 刷盘(保证至少 redo 持久化)
阶段二:commit
- Server 层写 binlog(刷盘)
- Server 通知 InnoDB 可以提交
- InnoDB 将 redo log 标记为 commit
最终 crash 不会造成:
- binlog 有记录但 redo 没有(主从不一致)
10.事务完成,向客户端返回 OK
此时:
- 数据已安全落盘(redo + binlog)
- 脏页以后再由 后台线程 写回磁盘(Flush,不影响事务提交)
完整流程顺序总结(面试可直接背)
面试官最喜欢的简答版(30秒版)
- 一条 SQL 执行时,Server 层负责解析、优化和生成执行计划,然后调用 InnoDB。
- InnoDB 读取数据页、加行锁,并在更新前生成 undo log,保证回滚和 MVCC。
- 更新在 Buffer Pool 中进行,并生成 redo log(prepare)。
- 提交阶段 Server 层写 binlog,然后通知 InnoDB 提交,redo log 标记为 commit。
- 这是两阶段提交,确保 binlog 和 redo 的一致性。
- 最后返回客户端 OK,而脏页稍后由后台线程刷盘。
- 作者:Sean Liu
- 链接:https://blog.liusx.dev//article/2b0749a0-584b-805f-bb4a-d9b0f73406f2
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。






