写mysql数据库日志的时机
数据库查询更新流程
首先不管是查询还是更新操作,客户端都会先跟 mysql 建立网络连接,并将 sql 发送到 server 层,经过分析器解析 sql 语法、优化器选择索引生成执行计划,最终给到执行器调用 InnoDB 的函数接口。
■对于读操作,InnoDB 存储引擎会先检查 Buffer Pool 中是否存在所需的 B+树数据页,如果存在则直接返回数据。如果 Buffer Pool 中没有所需的数据页,则会从磁盘中读取相应的数据页加载到 Buffer Pool 中,再返回数据。同时,如果查询的数据是热点数据,还会将数据页加入到自适应哈希索引豪华套餐中,加速后续的查询。
■对于写操作,则会先将数据写入 Buffer Pool,并生成相应的 Undo Log 记录,以便在事务回滚时能够恢复数据的原始状态。接下来,会将写操作记录到 Redo Log Buffer 中,这些 redo log 会周期性地写入到磁盘中的 Redo Log 文件中,就算数据库崩了,已提交的事务也不会丢失。对于辅助索引的更新操作,InnoDB 会将这些更新暂时存储在 Change Buffer 中,等到相关的索引页被读取到 Buffer Pool 时再执行实际的更新操作,从而减少磁盘 I/O,提高写入性能。同时,所有的变更都会记录到 server 层的 binlog 中,以便进行数据恢复。
问题
1. 修改时 Buffer Pool 里没有该数据,需要读盘吗?
需要先从磁盘读取。
UPDATE / DELETE 遵循"先读后写"原则:
如果 Buffer Pool 中没有目标数据页,InnoDB 必须先将该页从磁盘加载到 Buffer Pool。
然后在内存中的数据页上进行修改,并生成 Undo Log 和 Redo Log。
只有 INSERT 追加新页时可能不需要读原有数据页,但如果涉及唯一索引校验等,仍可能需要读盘。
2. Undo Log 是在事务执行过程中生成吗?
是的,实时生成。
每执行 INSERT、UPDATE、DELETE 时,InnoDB 会立即生成对应的 Undo Log。它的核心作用是:
事务回滚:恢复数据到修改前的状态。
MVCC:为其他事务提供一致性读视图。
如果等到提交时才生成,事务中途回滚将无法恢复数据。
3. Redo Log 是事务提交后才生成吗?
不是,执行过程中就会生成,提交时只是刷盘。
| 阶段 | Redo Log 行为 |
|---|---|
| 执行阶段 | 每次修改 Buffer Pool 时,同步将变更记录写入Redo Log Buffer(内存) |
| 提交阶段 | 将 Redo Log Buffer 中的内容fsync刷新到磁盘的 Redo Log 文件 |
目的是:即使提交后瞬间崩溃,已提交事务的修改也能通过 Redo Log 恢复,保证持久性。
4. Binlog 也是事务提交后才生成吗?
不是,执行过程中写入缓存,提交时刷盘。
执行阶段:事务中的每个写操作会实时写入Binlog Cache(会话级内存缓存)。
提交阶段:事务提交时,Binlog Cache 中的内容被刷新到磁盘的Binlog 文件中。
5. 辅助索引是什么?为什么延迟更新?主键索引要立即更新吗?
辅助索引(Secondary Index)
即非主键索引(二级索引),如普通索引、唯一索引(非主键)。其叶子节点存储的是主键值,而非完整数据行。
为什么用 Change Buffer 延迟更新?
这是 InnoDB 的写优化:
修改辅助索引时,如果对应的索引页不在 Buffer Pool中,不立即发起磁盘 I/O 去读该页。
而是将变更暂存到Change Buffer中,等该索引页后续被查询读入 Buffer Pool时,再合并更新。
好处:避免频繁的随机磁盘 I/O,显著提升写入性能。
主键索引需要立即更新吗?
是的,即时更新。
主键索引(聚簇索引)的叶子节点就是实际数据行,数据页和主键索引页是同一个东西。
修改数据时数据页已被加载到 Buffer Pool(见问题 1),所以主键索引直接在内存中完成,不存在"页不在内存"的场景,因此不需要 Change Buffer。
这是一个非常关键的区分点,涉及到 InnoDB 最核心的崩溃恢复机制。
6.事务回滚只通过 Undo Log,Redo Log 不参与回滚逻辑?
回滚时到底发生了什么?
当你执行ROLLBACK时,InnoDB 的流程是:
读取 Undo Log → 获取修改前的旧值 → 用旧值覆盖当前数据页 → 标记事务为已回滚
整个过程中完全没有用到 Redo Log。Redo Log 是"单向"的——它只负责记录"我做了什么修改",不提供"如何撤销"的信息。
那 Redo Log 在回滚后记录了什么?
回滚后,Redo Log 中仍然保留着该事务原来的修改记录,同时还会新增回滚操作产生的 Redo Log。
具体分为两层:
| 阶段 | Redo Log 内容 | 说明 |
|---|---|---|
| 执行 UPDATE | 记录了"将页X偏移Y处的值从 A 改为 B" | 这是原事务的修改 |
| 执行 ROLLBACK | 又记录了"将页X偏移Y处的值从 B 改回 A" | 回滚本身也在改数据页,必须记日志 |
为什么回滚也要写 Redo Log?
因为回滚操作也是在修改内存中的数据页。如果回滚过程中数据库崩溃了,重启后必须能恢复这个"回滚了一半"的状态。所以回滚动作本身也必须被 Redo Log 保护。
Undo Log 是"后悔药"(回滚用),Redo Log 是"保险单"(崩溃恢复用)。
回滚时只吃后悔药,但吃药这个动作(修改数据页)也会被保险单记录下来。
