[学习笔记]MySQL · Redo Log record编码格式
学习引用文章:
MySQL · 引擎特性 · Redo Log record编码格式
学习笔记仅为个人学习参考总结,内容基本来自于原文及其他额外资料的参考,阅读前请先移至原文参读,同时这里十分感谢原作者的文章分享。
编码方式
不同的编码方式会影响数据库的性能,体现在两个方面:
影响redo log的大小:占用空间越小,越能减少写放大,提高写性能;减少崩溃恢复时redo log的扫描及物理复制的网络传输开销。
影响redo log的应用速度,速度越快,越能减少崩溃恢复的时间。
Mysql 8.0的Redo Log Record编码
针对记录的redo log record中包含的一些字段数值,设计了一些编码规则来压缩存储。
压缩算法
32位压缩格式(占用1~5字节)
前缀连续出现0的情况:
25个0,1字节:0nnnnnnn 表示0~127
18个0,2字节:10nnnnnn nnnnnnnn 表示128~16511
11个0,3字节:110nnnnn nnnnnnnn nnnnnnnn 表示16512~2113663
4个0,4字节:1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn 表示2113664~270549119
前缀连续出现1的情况:
22个1,2字节:111110nn nnnnnnnn 表示0xFFFFFC00~0xFFFFFFFF
15个1,3字节:1111110n nnnnnnnn nnnnnnnn 表示0xFFFE0000~0xFFFFFBFF
8个1,4字节:11111110 nnnnnnnn nnnnnnnn nnnnnnnn 表示0xFF000000~0xFFFDFFFF
其他情况,占用5字节:11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn
适用场景:适用于比较小的值或特别大的值频繁出现的情况,比如space_id和page_no。
64位低压缩率格式(占用5~9字节)
高低位设计:将64bit的值均分,高位的32bit使用32位压缩格式存储(1~5字节),低位的32bit不压缩直接存储(4字节)。
适用场景:适用于高位32bit部分的值特别小或特别大,同时低位32bit部分的值分布比较均匀的情况。
64位高压缩率格式(占用1~11字节)
高低位设计:将64bit的值均分,高位的32bit都是0,则直接写入低位32bit的无压缩格式(1~5字节);否则,首个字节写入0xFF,之后写入高位32bit的压缩格式(2~6字节),然后写入低位32bit的压缩格式(1~5字节)。
适用场景:适用于存储比较小的值。
编码格式
redo log record有50多种类型,每个record的第一个字节用来标识类型值,也就是8bit:
1bit:single_rec_flag,1标识单条record组成的mtr,0表示多条record组成的mtr。
7bit:表示类型type。
mtr:mini-transaction,小事务,在DML操作期间,在物理层上改变内部数据结构。小事务没有回滚的概念,多个小事务可以在一个事务中发生。小事务通常发生在常规事务中,将信息写入崩溃恢复期间使用的redo log,也可以发生在后台线程清理处理期间。
第一个字节之后通常是space_id和page_no,各自占用1~5字节,使用32位压缩格式存储,也有其他类型的不包含,像MLOG_TABLE_DYNAMIC_META类型,用于记录表的auto_inc值。
再之后就是各个record类型的body部分,具有特定的编码方式。
MariaDB的Redo Log Record编码
MariaDB从10.2版本之后开始使用MySQL 5.7的InnoDB引擎,进而也使用了InnoDB的redo log record编码方式,但是从10.6版本之后对redo log record编码进行了优化。
InnoDB中redo log的性能问题:
record编码中没有包含本身的长度,在crash recover时需要依次解析才能得到完成的record。
record编码中保存了一些需要mlog_parse_index函数来转换的冗余的类型。
连续多个针对同一page修改的record,会重复多次写入space_id和page_no,导致写放大和crash recovery时的解析消耗。
优化改动:
缩减type的数量为12个(7个代表page改动,5个代表文件操作)。
调整record的header格式,
same_page:标识record是否和上一条record指向同一个page。
log type:12个record类型。
add_len:record的长度,标识长度范围为1~15的record,超过部分则使用32位压缩格式存储,总长度就是15+add_len。
注意log type中的EXTENDED类型:由于新编码方式在记录undo写入时生成的record所占用空间反而比之前InnoDB的编码方式要大,所以使用EXTENDED类型(按照原InnoDB的方式记录)来保证record大小不会膨胀。
优化结果:针对update场景的性能测试,修改了redo log record编码后,crash recovery的性能可以提高大约15%。
身未动,心已远。
把一件事做到极致就是天分!