我们知道Mysql分Server层和存储引擎层。Server层负责处理连接,解析,执行等。引擎层负责数据的读写。
执行流程
所以大概的执行流程也分Server层和引擎层
1,Server层
- 建立客户端连接,验证用户权限。
- 若启用缓存,会检查是否命中
- 分析器进行语法,词法的分析
- 优化器选择最优执行计划
- 执行器调用引擎层接口处理
2,引擎层
- 数据定位,通过索引(如主键)定位目标行,若数据页不在内存,则从磁盘加载
- 加锁与日志记录,加排他锁,防止并发修改。将旧数据写入Undo Log日志,用于回滚与MVCC的多版本并发控制。写入Binlog记录逻辑变更。
- 修改数据并提交
- 释放锁资源
UPDATE过程中bin日志,redo log日志,undo log日志是怎么记录的?
首先我们需要知道每种日志的作用是什么样的。
一、Binlog(二进制日志)
记录方式:
-
逻辑日志:记录的是“逻辑操作”(如
UPDATE users SET name='John' WHERE id=1;
),而不是物理页的修改。 -
写入时机:
-
在事务提交时,由MySQL Server层的执行器写入。
-
在两阶段提交(2PC)的第二阶段(Commit阶段)持久化。
-
-
存储格式:
-
STATEMENT
:记录原始SQL语句。 -
ROW
:记录实际修改的行数据(默认模式)。 -
MIXED
:混合模式,由MySQL自动选择。
-
作用:
-
主从复制:从库通过重放Binlog实现数据同步。
-
数据恢复:通过
mysqlbinlog
工具解析Binlog,恢复误操作数据。 -
审计:记录所有数据变更操作。
二、Redo Log(重做日志)
记录方式:
-
物理日志:记录的是数据页的物理修改(例如“将页号为3的页中偏移量100的位置写入值’John’”);
-
写入时机:
-
在事务执行过程中,由InnoDB存储引擎实时写入(顺序写入)。
-
分为两个阶段:
-
Prepare阶段:事务修改前,先写入Redo Log(状态为
Prepare
)。 -
Commit阶段:事务提交时,将状态改为
Commit
。
-
-
-
存储结构:
-
循环写入,文件固定大小(如
ib_logfile0
和ib_logfile1
)。
-
作用:
-
崩溃恢复:MySQL宕机后,通过重放Redo Log将未刷盘的脏页恢复。
-
Write-Ahead Logging (WAL):确保数据修改先写日志再写磁盘,提升性能(避免随机写)。
-
保证持久性:即使宕机,已提交事务的修改不会丢失。
三、Undo Log(回滚日志)
记录方式:
-
逻辑日志:记录修改前的旧值(例如
id=1
的原值name='Alice'
)。 -
写入时机:
-
在事务修改数据前,由InnoDB生成Undo Log。
-
存储在Undo Tablespace(MySQL 8.0默认独立存储)。
-
-
存储结构:
-
链式结构:多个事务的Undo Log通过指针连接,支持多版本控制(MVCC)。
-
作用:
-
事务回滚:事务失败时,通过Undo Log恢复旧值。
-
MVCC(多版本并发控制):
-
为其他事务提供一致性读视图(ReadView)。
-
例如,在
REPEATABLE READ
隔离级别下,其他事务读取的是Undo Log中的旧版本数据。
-
-
避免脏读:未提交事务的修改对其他事务不可见。
日志记录的过程
-
事务开始:
用户执行
UPDATE users SET name='John' WHERE id=1;
-
Undo Log记录旧值:
InnoDB将
id=1
的原数据(name='Alice'
)写入Undo Log。 -
Redo Log(Prepare阶段):
将数据页的物理修改写入Redo Log,状态为
Prepare
。 -
Binlog写入:
执行器将逻辑操作(
UPDATE
语句或行变更)写入Binlog。 -
Redo Log(Commit阶段):
事务提交时,将Redo Log状态改为
Commit
。 -
提交完成:
释放行锁,数据页在Buffer Pool中标记为脏页,异步刷盘。
执行UPDATE过程中,MYSQL崩溃,重启后MySQL是如何处理的?
如果MySQL在写入Binlog后突然宕机:
-
重启时发现Redo Log状态为
Prepare
且存在对应的Binlog。 -
根据两阶段提交规则,重放Redo Log完成事务提交。
如果未写入Binlog就宕机:
-
Redo Log状态为
Prepare
但没有对应的Binlog,事务会被回滚。