引言:
mysql中日志文件是非常重要,mysql的各种特性和功能都是基于日志文件实现的,本文将详细介绍mysql的日志文件
一、日志类型(仅介绍重要的)
1.Undo Log
(1)作用
- 实现事务的原子性(Atomicity)。
- 用于事务回滚(ROLLBACK),当事务执行失败或显式回滚时,可以通过 Undo Log 恢复到事务开始前的状态。
- 支持多版本并发控制(MVCC),实现非锁定读(如
SELECT
不加锁也能读到历史版本)。
(2)存储位置
- 存储在 InnoDB 存储引擎的表空间中(可以是系统表空间或独立的 Undo 表空间)。
- 从 MySQL 5.6 开始支持独立的 Undo 表空间(通过
innodb_undo_tablespaces
配置)。
(3)工作机制
- 当一条记录被修改时,InnoDB 会先将修改前的旧值(旧版本)写入 Undo Log。
- 每个事务有自己的 Undo Log 记录,形成一个链表(Undo Log Chain)。
- 当事务提交后,Undo Log 并不会立即删除,而是标记为"可清理"状态,供 MVCC 使用。
- 后台线程(Purge Thread)在确认没有事务需要这些旧版本后,才会真正删除 Undo 日志
(4)示例
sql
BEGIN;
UPDATE users SET age = 25 WHERE id = 1;
-- 此时,原 age 值(比如20)被写入 Undo Log
ROLLBACK;
-- 使用 Undo Log 回滚,age 恢复为 20
2. Redo Log
1. 作用
- 保证事务的持久性(Durability)。
- 确保即使在数据库崩溃后,已提交的事务修改也不会丢失。
- 通过 WAL(Write-Ahead Logging,预写日志)机制,先写日志再写数据页。
2. 存储位置
- 物理文件,位于 MySQL 数据目录下,通常为
ib_logfile0
和ib_logfile1
。 - 文件大小固定(由
innodb_log_file_size
控制),循环写入。
3. 工作机制
- 事务执行过程中,对数据页的修改会先记录到 Redo Log Buffer(内存中)。
- 当满足一定条件(如事务提交、Buffer满、每秒刷新等),Redo Log Buffer 会被刷新到磁盘的 Redo Log 文件中。
- 数据页的真正修改可以异步写入磁盘(由后台线程完成),提高性能。
- 数据库崩溃恢复时,通过 Redo Log 重放(replay)已提交但未落盘的事务操作,恢复数据。
4. 关键参数
innodb_log_file_size
:单个日志文件大小(建议设置为 1~2GB)。innodb_log_files_in_group
:日志文件数量(默认2)。innodb_flush_log_at_trx_commit
:控制日志刷盘策略:1
:每次事务提交都刷盘(最安全,性能略低)。0
:每秒刷一次,事务提交不刷盘(性能高,可能丢失1秒数据)。2
:事务提交写入 OS 缓存,每秒刷盘(折中方案)。
5. 示例
sql
BEGIN;
UPDATE users SET age = 30 WHERE id = 1;
COMMIT;
-- 提交时,Redo Log 写入磁盘,即使此时数据页未写入磁盘,崩溃后也能恢复
sql
BEGIN; UPDATE users SET age = 30 WHERE id = 1; COMMIT; -- 提交时,Redo Log 写入磁盘,即使此时数据页未写入磁盘,崩溃后也能恢复
3.Binlog(二进制文件)
(1)作用
- 记录所有修改数据的 SQL 语句或行变更(取决于格式)。
- 用于数据库的主从复制(Replication) 和 数据恢复(Point-in-Time Recovery)。
- 由 MySQL Server 层维护,与存储引擎无关(所有引擎都能记录 Binlog)。
(2)存储位置
- 文件形式,位于 MySQL 数据目录下,如
mysql-bin.000001
、mysql-bin.000002
等。 - 可以配置自动删除过期日志(通过
expire_logs_days
或binlog_expire_logs_seconds
)。
(3)日志格式(三种模式)
全屏复制
格式 | 说明 | 优缺点 |
---|---|---|
STATEMENT | 记录 SQL 语句本身 | 日志量小,但可能在从库产生不一致(如使用 NOW() 函数) |
ROW | 记录每一行数据的变更(推荐) | 安全、精确,适合复制,但日志量大 |
MIXED | 混合模式,MySQL 自动选择 | 一般默认使用,兼顾安全与性能 |
(4)写入时机
- 事务提交时,由 MySQL Server 层将变更写入 Binlog(在存储引擎提交之前或之后,取决于参数)。
- 通过
sync_binlog
控制刷盘频率:0
:由操作系统决定(性能高,风险高)。1
:每次事务提交都刷盘(最安全,性能稍低)。N
:每 N 个事务提交刷一次。
(5)使用场景
- 主从复制:主库 Binlog 发送给从库,从库通过 SQL Thread 回放日志。
- 数据恢复 :通过
mysqlbinlog
工具解析 Binlog,恢复到某个时间点。
4.Doublewrite Buffer(双写缓冲)
✅ 是否属于"日志"?
严格来说不是日志文件,但它是 一种保障数据页写入一致性的机制,常与 Redo Log 配合使用,防止"部分写问题"(partial page write)。
🔍 作用
- 防止在数据库崩溃时出现"页断裂"(Page Corruption)。
- 当 InnoDB 将脏页刷新到磁盘时,如果写入过程中断电,可能导致页面只写了一半(512字节 out of 16KB),造成数据损坏。
- Doublewrite Buffer 先将页面写入一个连续的、安全的区域(系统表空间中的双写缓冲区),再写入实际的数据文件位置。
📍 工作流程:
- 脏页从 Buffer Pool 刷出时,先批量写入 Doublewrite Buffer 区域(物理上连续)。
- 再将这些页写入各自在
.ibd
文件中的目标位置。 - 崩溃恢复时,如果发现某页校验失败,可以从 Doublewrite Buffer 中恢复完整的副本。
5.Change Buffer(变更缓冲)
✅ 是否属于"日志"?
不是传统日志,但它记录的是对二级索引页的延迟修改操作,具有"延迟写 + 缓冲"的特性,类似轻量级日志。
🔍 作用
- 提高 DML 操作(INSERT/UPDATE/DELETE)性能,尤其是在大量随机写入场景下。
- 对于非唯一二级索引的更新,如果不影响主键索引,InnoDB 会将修改暂存到 Change Buffer,而不是立即读取并修改对应的索引页(避免随机 I/O)。
- 后续当该页被加载到内存时,再进行合并(merge)。
🔄 合并时机:
- 查询访问该页时。
- 后台线程定期合并。
- 系统空闲或刷新脏页时。
6.Error Log(错误日志)
属于 MySQL Server 层,但 InnoDB 的严重错误也会写入其中
🔍 作用
- 记录 InnoDB 初始化、崩溃、恢复、死锁、表空间异常等关键事件。
- 是排查 InnoDB 故障的重要依据。
7. InnoDB Recovery Logs(恢复日志信息)
这不是独立文件,而是指 InnoDB 在启动时通过 Redo Log 自动执行恢复过程的日志输出,通常打印在 Error Log 中。
8.Slow Query Log(慢查询日志)
用来分析 InnoDB 表的锁等待、长事务、全表扫描等问题。
二、sql语句执行过程中日志写入顺序和触发时机
示例 SQL
sql
BEGIN;
UPDATE users SET age = 30 WHERE id = 1;
COMMIT;
1.整体流程概览
阶段 | 操作 | 写入日志 |
---|---|---|
1. 开始事务 | BEGIN |
无日志写入 |
2. 执行 UPDATE | 修改数据页 | 写 Undo Log + Redo Log(内存) |
3. 提交事务 | COMMIT |
Redo Log 刷盘 → 写 Binlog → Binlog 刷盘 → InnoDB 提交 |
2.详细时间线:
时间点 | 操作 | 写入内容 | 写入位置 | 是否刷盘(持久化) |
---|---|---|---|---|
T0 | BEGIN; |
无 | - | ❌ |
T1 | UPDATE ... |
旧值写入 Undo Log | Undo Log Buffer(内存) | ❌ |
T1 | UPDATE ... |
修改数据页 | Buffer Pool(内存) | ❌ |
T1 | UPDATE ... |
生成 Redo Log 记录 | Redo Log Buffer(内存) | ❌ |
T2 (Prepare) | COMMIT 开始 |
事务状态 → PREPARED | Redo Log Buffer | ✅ (fsync ) |
T2 (Prepare) | COMMIT 开始 |
所有 Redo Log 刷盘 | ib_logfile* |
✅ |
T2 (Commit) | 写 Binlog | 更新事件写入 Binlog | Binlog Cache → .binlog |
✅ (fsync , sync_binlog=1 ) |
T2 (Commit) | 最终提交 | 事务状态 → COMMITTED | InnoDB 内部结构 | ✅(通过 Redo Log) |
3.💥 崩溃恢复场景分析
假设在不同阶段发生崩溃,MySQL 如何恢复?
崩溃时间点 | 恢复行为 |
---|---|
在 UPDATE 后,未 COMMIT |
重启后回滚该事务(通过 Undo Log) |
在 Prepare 阶段后,未写 Binlog | 重启后发现 PREPARED 事务,但无对应 Binlog → 回滚 |
在 Binlog 写完后,未最终提交 | 重启后发现 PREPARED 事务且有 Binlog → 提交(保证一致性) |
成功提交后崩溃 | 数据已持久化,正常启动 |
三、总结:
名称 | 类型 | 所属层级 | 主要用途 | 是否持久化 |
---|---|---|---|---|
Undo Log | 日志 | InnoDB | 回滚、MVCC | ✅ |
Redo Log | 日志 | InnoDB | 崩溃恢复、持久性 | ✅ |
Doublewrite Buffer | 安全机制 | InnoDB | 防止页断裂 | ✅ |
Change Buffer | 缓冲结构 | InnoDB | 延迟二级索引更新 | ❌(数据最终落盘) |
Error Log | 日志 | Server 层 | 记录 InnoDB 错误 | ✅ |
Transaction System / Rollback Segments | 内部结构 | InnoDB | 事务管理元数据 | ✅ |