mysql 执行sql流程概述
sql执行流程
解析器(Parser)
作用:把 SQL 文本转换成数据库能理解的结构化形式。
具体做的事情:
- 词法分析(Lexical Analysis)
- 把 SQL 文本拆成 token(关键字、表名、字段名、符号等)。
- 语法分析(Syntax Analysis)
- 根据 SQL 语法规则生成 解析树(Parse Tree)。
- 检查 SQL 是否符合语法规范。
- 例如:
SELECT id, name FROM users WHERE age > 18;
会生成一棵树,表示SELECT
→FROM users
→WHERE age > 18
。
- 初步语法检查
- 检查关键字顺序、括号匹配、函数调用是否合法。
预处理器(Preprocessor / Preparser)
作用:在语义层面检查 SQL,保证执行时可以找到所有对象和权限。
具体做的事情:
- 权限检查
- 判断用户是否有权限访问表或列。
- 对象存在性检查
- 检查表、列、视图、函数等是否存在。
- 标识符解析
- 将 SQL 中的表名、列名、别名解析成内部对象指针。
- 语义检查
- 检查列类型匹配、函数参数合法性、聚合函数是否合理等。
- 生成准备执行的解析树
- 解析树被增强,带上表、列的对象信息,为优化器使用。
⚠️ 注意:预处理器不处理执行策略,只检查语义和权限。
MVCC 的处理流程(读操作)
InnoDB 通过 多版本并发控制(MVCC) 来实现非阻塞读(一致性读,Consistent Read)。
关键点:
- 每行数据在内部存储两个隐藏列:
DB_TRX_ID
:最近修改这行的事务 IDDB_ROLL_PTR
:指向 Undo Log 的指针(保存修改前的版本)
读操作流程
- 事务 T1 执行 SELECT 查询(非锁定读):
- InnoDB 会检查行的
DB_TRX_ID
。 - 对每行:
- 如果
DB_TRX_ID
< T1 的事务开始时间 → 可见。 - 如果
DB_TRX_ID
> T1 的事务开始时间 → 不可见,读 Undo Log 中旧版本。
- 如果
- InnoDB 会检查行的
- 从 Undo Log 获取快照:
- Undo Log 记录了行被修改前的旧值。
- T1 会根据事务开始时间回溯到合适的旧版本。
- 保证一致性读:
- SELECT 看到的是 事务开始时刻的数据快照,不会被其他事务未提交的修改影响。
更新事务对索引的处理
当事务 T2 执行 UPDATE/INSERT/DELETE:
- 索引和数据页修改顺序:
- InnoDB 先更新索引(叶子节点),再修改数据页。
- 这是为了保证聚簇索引一致性和快速定位行。
- 事务未提交时的可见性:
- 未提交事务修改的数据对其他事务是 不可见的(默认隔离级别是 Repeatable Read / Read Committed)。
- InnoDB 会在索引页记录事务 ID:
- 其他事务扫描索引时,如果遇到行被未提交事务修改,会判断不可见,从而跳过该行。
- 所以 索引修改不会影响其他事务读取逻辑,只会在锁冲突时被阻塞(比如 SELECT … FOR UPDATE)。
- 锁和阻塞情况:
- 如果其他事务做的是 共享读(一致性读) → 不受影响。
- 如果其他事务做的是 修改或 FOR UPDATE → 会等待未提交事务提交或回滚。
sql执行流程图
客户端 SQL↓
MySQL Server 接收↓
解析器 (Parser) → 词法 & 语法分析 → 解析树↓
预处理器 (Preprocessor) → 权限检查 & 对象解析 → 语义合法的解析树↓
优化器 (Optimizer) → 逻辑优化 & 访问路径选择 → 执行计划↓
执行引擎 (Execution Engine) → 真正访问数据页,生成结果↓┌──────────────┐│ 读操作: MVCC ││ 写操作: ││ - Buffer Pool 数据页修改│ - 生成 Undo Log│ - 生成 Redo Log└──────────────┘↓
事务提交 (COMMIT)↓- Redo Log 刷盘- 标记事务已提交- Undo Log 保留/异步清理↓
数据页异步落盘(后台线程)↓
返回客户端结果
数据更新流程
[应用层 INSERT/UPDATE]|v[Buffer Pool 页修改]/ \
[聚簇索引页] [二级索引 -> Insert Buffer]|v[Undo Log in Buffer Pool] <-- 内存记录旧值|v[Redo Log in Log Buffer] <-- 持久化保证|[事务提交? flush redo log?]|v[磁盘刷新]/ \
[聚簇索引页刷盘] [二级索引页刷盘 via Insert Buffer + Doublewrite]^|Undo Log 异步写入 undo tablespace
崩溃恢复点标注在:
-
Redo Log:保证事务提交数据可重做
-
Undo Log:回滚未提交事务
-
Doublewrite:保证页完整性
-
Insert Buffer:二级索引也能恢复
-
Undo Log 不需要像 Redo Log 那样同步 flush,每次事务提交主要依赖 Redo Log 保证持久性。
-
Undo Log 的刷盘是异步的,主要为了释放内存和 MVCC 一致性。