
本文共 2240 字,大约阅读时间需要 7 分钟。
概述
InnoDB的事务日志包括redo log
和undo log
。redo log
用于支持事务前滚操作,而undo log
用于支持事务回滚操作。两者在事务持久化中扮演着重要角色。
1. redo log
1.1 redo log与二进制日志的区别
redo log
是InnoDB层特有的日志类型,只记录InnoDB层中表的修改。与之相比,二进制日志(binlog
)是服务器层产生的日志,支持所有存储引擎。二进制日志通常记录的是逻辑操作(如SQL语句),而redo log
记录的是物理页的修改。
二进制日志:
- 生成在服务器层,不受存储引擎类型影响。
- 记录的是逻辑操作(如插入、更新、删除等)。
- 记录顺序与提交顺序一致。
- 在提交时,二进制日志会先于
redo log
写入磁盘。
redo log:
- 生成在InnoDB层,仅记录InnoDB表的修改。
- 记录的是物理页的变化。
- 提交时,
redo log
会被优先写入磁盘。
1.2 redo log的基本概念
redo log
主要由两个部分组成:
redo log buffer
):用于存储临时的日志数据。redo log file
):存储持久化的日志数据。redo log
的写入过程:
- 修改操作完成后,将数据页从内存缓冲到磁盘。
- 在提交时,
redo log buffer
中的日志会被刷入磁盘。
redo log
的结构:
- 每个日志块(
redo log block
)大小为512字节。 - 包含日志块头(12字节)、日志块尾(8字节)和日志主体(492字节)。
日志块头包含以下信息:
log_block_hdr_no
:日志块在缓冲区的位置ID。log_block_hdr_data_len
:日志块已记录的大小。log_block_first_rec_group
:日志块中第一个记录的偏移位置。log_block_trl_no
:日志块的序列号。
日志块尾用于验证日志块的完整性。
1.3 日志块(log block
)
redo log
以日志块为单位存储,大小为512字节。每个日志块包含:
- 约束条件记录(
redo_log_type
):表示日志类型。 - 表空间ID(
space
):记录表空间的ID。 - 页偏移量(
page_no
):表示数据页的偏移量。 - 约束条件日志体(
redo_log_body
):记录实际的修改内容。
1.4 log group与redo log file
log group
由多个大小相同的redo log file
组成。每个组默认包含2个文件,文件大小由innodb_log_file_size
变量决定。
log group
的写入规则:
- 首先写入第一个文件(
ib_logfile0
),当文件满载时切换到第二个文件(ib_logfile1
)。 - 当第二个文件满载时,第一个文件会被清空部分空间,继续写入。
1.5 redo log的格式
redo log
记录的是数据页的物理变化。每个日志块的日志主体部分包含:
- 约束条件记录(1字节)。
- 表空间ID(可压缩,4字节)。
- 页偏移量(可压缩,4字节)。
- 约束条件日志体(492字节)。
1.6 日志刷盘规则
日志刷盘的规则:
innodb_flush_log_at_timeout
控制)。innodb_flush_log_at_trx_commit
变量控制提交时的刷盘策略:
- 值为1:每提交一次事务就刷盘。
- 值为0:每秒刷盘一次。
- 值为2:每提交一次事务只写入缓冲区,定时刷盘。
1.7 数据页刷盘规则及检查点
数据页的刷盘(脏页刷盘)与日志刷盘不同,只有在检查点时才会刷盘。检查点触发时:
- 脏页刷盘。
- 脏日志刷盘。
undo log
的恢复速度快于binlog
,因为undo log
记录的是逻辑操作,而binlog
记录的是物理操作。
2. undo log
2.1 基本概念
undo log
用于提供回滚和多版本控制(MVCC)。每个undo log
记录包含事务ID和指针。
undo log
的存储方式:
- 以段为单位存储,每个段包含1024个
undo log
记录。 - 默认存放在共享表空间中。
2.2 和undo log相关的变量
innodb_undo_logs
:默认为128,控制回滚段数量。innodb_undo_directory
:默认为数据目录。innodb_undo_tablespaces
:默认为0,控制undo表空间数量。
undo log
的记录机制:
- 插入操作不需要记录。
- 删除操作记录对应的插入操作。
- 更新操作记录对应的逆操作。
3. binlog与事务日志的先后顺序及group commit
在提交时,二进制日志先于redo log
写入磁盘。binlog
和redo log
的写入机制:
binlog
写入内存。binlog
刷盘。redo log
和undo log
的刷盘。group commit
优化:
- 将多个事务的
binlog
一次性刷盘,提升性能。 - MySQL5.6引入了新的机制,确保在
binlog
和redo log
同时支持group commit
。
通过合理设置sync_binlog
和innodb_flush_log_at_trx_commit
变量,可以优化日志刷盘性能。