vlambda博客
学习文章列表

[学习笔记]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%。


身未动,心已远。

把一件事做到极致就是天分!