MySQL(十七)】redo log

mysql使用WAL机制,在执行更新操作时并不会直接写盘,而是先记redo log。

redo log格式

MySQL(十七)】redo log_第1张图片

(本篇图片全部来自掘金小册中《MySQL是怎样运行的》一书)

type:innodb有很多类型的redo log格式,比如指定不同的偏移量等等;

data:日志详细内容;

 

mini-transaction

一条sql更新语句,其实需要会涉及很多页面更新逻辑,比如更新聚簇索引,更新二级索引等,在更新索引的时候,可能需要分裂节点,新申请页面等等。innodb规定,这些一个基础的操作必须是原子的,比如更新索引需要更新page页内的目录项信息,header信息以及数据行信息,那这些更新必须是原子的,不能只执行一部分。所以,redo log必须以组的形式提交,也叫作mini-transaction。

 

那么怎么识别一组redo log呢?

innodb规定一组redo log后会是一条特殊类型的redo log,专门用来做为结尾标记。

所以,事务和redo log的关系是这样的:

MySQL(十七)】redo log_第2张图片

(本篇图片全部来自掘金小册中《MySQL是怎样运行的》一书)

 

redo log block

redo log使用一种大小为512字节的特殊类型的页存放redo log,这种页也叫作block。

MySQL(十七)】redo log_第3张图片

(本篇图片全部来自掘金小册中《MySQL是怎样运行的》一书)

 

redo log buffer

类似于buffer pool,redo log也是用了缓存,叫做redo log buffer。内存中会开辟若干个block来存放redo log缓存。redo log写入是按照mini-transaction分组的,内存中有一个buffer_free变量,指向buffer中下一个可写入位置。

MySQL(十七)】redo log_第4张图片

(本篇图片全部来自掘金小册中《MySQL是怎样运行的》一书)

 

LSN

log sequence number,redo log日志序号,递增,初始值是8704,每写入一条日志,就将LSN值增加日志长度,这个长度的计算会考虑header和trailer。

 

flushed_to_disk_lsn

记录已经被刷到磁盘的redo log buffer位置。

 

redo log刷盘时机:

1.redo log满了;

2.后台线程;

3.事务提交,当然这个并不是绝对的,取决于数据库innodb_flush_log_at_trx_commit配置。

4.buffer pool满了,需要刷脏页时;

5.checkpoint;

 

innodb_flush_log_at_trx_commit配置

参数决定了事务提交时的行为。0:代表每一次提交只是写入到redo log buffer,如果mysql进程挂了,会丢数据,这是不安全的;1:代表每一次提交都写入磁盘,fsync;2:代表每一次提交都写入操作系统写缓冲,write,如果操作系统挂了,会丢数据;

 

两段式提交

redo log与binlog需要两段式提交,防止只有一个写入成功,这样会出现数据不一致;如果只有redo log成功,从库不一致;反之,主库不一致;

大致过程:

redo log prepare;

binglog write;

commit;

 

如何刷脏页?

不能只用redo log,还需要将对应的页读入内存,然后使用redo log更新内存,再刷磁盘;

你可能感兴趣的:(mysql)