[MySQL] 事务日志重做日志详情 - 4.1 重做日志缓冲区:
Mini-Transaction:
MySQL把对底层页面中的一次原子访问的过程称之为一个Mini-Transaction
,简称mtr
,比如,向某个素引对应的B+树中插入一条记录的过程就是一个Mini-Transaction
。一个所谓的mtr
可以包含一组redo日志,在进行崩溃恢复时,这一组redo日志作为一个不可分割的整体。
一个事务可以包含若干条语句,每一条语句其实是由若干个mtr
组成,每一个mtr
又可以包含若干条redo日志。画个图表示它们的关系就是这样:
Redo 日志写入log buffer:
向log buffer
中写入redo日志的过程是顺序的,也就是先往前边的block中写,当该block的空闲空间用完之后再往下一个block中写。当我们想往log buffer
中写入redo日志时,第一个遇到的问题就是应该写在哪个block的哪个偏移量处,所以InnoDB的设计者特意提供了一个称之为buf_free
的全局变量,该变量指明后续写入的redo日志应该写入到log buffer
中的哪个位置,如图所示:
一个mtr执行过程中可能产生若干条redo日志,这些redo日志是一个不可分割的组,所以其实并不是每生成一条redo日志,就将其插入到log buffer
中,而是每个mtr运行过程中产生的日志先暂时存到一个地方,当该mtr结束的时候,将过程中产生的一组redo日志再全部复制到log buffer
中。我们现在假设有两个名为T1、T2的事务,每个事务都包含2个mtr,我们给这几个mtr命名一下:
-
事务T1的两个mtr分别称为
mtr_T1_1
和mtr_T1_2
。 -
事务T2的两个mtr分别称为
mtr_T2_1
和mtr_T2_2
。
每个mtr都会产生一组redo日志,用示意图来描述一下这些mtr产生的日志情况:
不同的事务可能是并发执行的,所以T1、T2之间的mtr可能是交替执行的。每当一个mtr执行完成时,伴随该
mtr生成的一组redo日志就需要被复制到log buffer
中,也就是说不同事务的mtr可能是交替写入log buffer
的,我们画个示意图(为了美观,我们把一个mtr中产生的所有的redo日志当作一个整体来画):
有的mtr产生的redo日志量非常大,比如mtr_t1_2
产生的redo日志占用空间就比较大,占用了3个block来存储。
Redo log block 结构图:
一个redo log block是由:日志头、日志体、日志尾组成。日志头占用12个字节,日志尾占用8个字节,所以一个block真正能存储数据就是512-12-8=492字节。
真正的redo日志都是存储到占用496字节大小的log block body
中,图中的log block header
和log block trailer
存储的是一些管理信息。我们来看看这些所谓的管理信息都有什么:
上一篇: Elasticsearch 索引片数量和大小分配策略
下一篇: 技术产品|阿里云存储白皮书 第2章