MySQL · 源码分析 · Innodb 引擎Redo日志存储格式简介

本文涉及的产品
RDS Agent(兼容OpenClaw),2核4GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: MySQL有多种日志。不同种类、不同目的的日志会记录在不同的日志文件中,它们可以帮助你找出mysqld内部发生的事情。比如错误日志:用来记录启动、运行或停止mysqld进程时出现的问题;查询日志:记录建立的客户端连接和执行的语句;二进制日志:记录所有更改数据的语句,主要用于逻辑复制;慢日志:记录所有执行时间超过long_query_time秒的所有查询或不使用索引的查询。而对MySQL中最常用的事

MySQL有多种日志。不同种类、不同目的的日志会记录在不同的日志文件中,它们可以帮助你找出mysqld内部发生的事情。比如错误日志:用来记录启动、运行或停止mysqld进程时出现的问题;查询日志:记录建立的客户端连接和执行的语句;二进制日志:记录所有更改数据的语句,主要用于逻辑复制;慢日志:记录所有执行时间超过long_query_time秒的所有查询或不使用索引的查询。而对MySQL中最常用的事务引擎innodb,redo日志是保证事务一致性非常重要的。本文结合MySQL版本5.6为分析源码介绍MySQL innodb引擎的重做(Redo)日志存储格式。

Redo日志

任何对Innodb表的变动, redo log都要记录对数据的修改,redo日志就是记录要修改后的数据。redo 日志是保证事务一致性非常重要的手段,同时也可以使在bufferpool修改的数据不需要在事务提交时立刻写到磁盘上减少数据的IO从而提高整个系统的性能。这样的技术推迟了bufferpool页面的刷新,从而提升了数据库的吞吐,有效的降低了访问时延。带来的问题是额外的写redo log操作的开销。而为了保证数据的一致性,都要求WAL(Write Ahead Logging)。而redo 日志也不是直接写入文件,而是先写入redo log buffer,而是批量写入日志。当需要将日志刷新到磁盘时(如事务提交),将许多日志一起写入磁盘。关于redo的产生及其生命周期详细过程,详见:https://yq.aliyun.com/articles/219。

Redo日志文件格式

MySQL redo日志是一组日志文件,它们会被循环使用。Redo log文件的大小和数目可以通过特定的参数设置,详见innodb_log_file_size 和 innodb_log_files_in_group 。

日志组结构

在实现上日志组是由定义在log0log.h中的log_group_t结构体来表示的。在日志组结构体定义中含有以下重要信息:
日志文件的大小(file_size):记录日志组内每个日志文件的大小,通过参数innodb_log_file_size配置。
日志文件的个数(n_files): 记录这个日志组中的文件个数,,通过参数innodb_log_files_in_group配置。
Checkpoint相关的信息:只有做完checkpoint后,其之前的日志才可以不再保留,否则系统崩溃时则无法恢复。在系统崩溃后的恢复,需要从checkpoint点开始。但我们需要把checkpoint的相关信息持久化的保存下来,才能在系统崩溃时不会丢失这些检查点相关的信息。Checkpoint相关的信息只存放在ib _logfile0中。

日志文件结构

每个日志文件的前2048字节是存放的文件头信息。头结构定义在”storage/innobase/include/log0log.h” 中。其在重做日志文件内的布局如下图所示:

Redo 日志存储排列

其中几个重要的字段在这里加以说明:
日志文件头共占用4个OS_FILE_LOG_BLOCK_SIZE的大小,这里对部分字段做简要介绍:
1) LOG_GROUP_ID               这个log文件所属的日志组,占用4个字节,当前都是0;
2) LOG_FILE_START_LSN     这个log文件记录的开始日志的lsn,占用8个字节;
3) LOG_FILE_WAS_CRATED_BY_HOT_BACKUP   备份程序所占用的字节数,共占用32字节;
4) LOG_CHECKPOINT_1/LOG_CHECKPOINT_2   两个记录InnoDB checkpoint信息的字段,分别从文件头的第二个和第四个block开始记录,只使用日志文件组的第一个日志文件。
从地址2KB偏移量开始,其后就是顺序写入的各个日志块(log block)。

日志块结构

所有的redo日志记录是以日志块为单位组织在一起的,日志块的大小为OS_FILE_LOG_BLOCK_SIZE(默认值为512字节),所有的日志记录以日志块为单位顺序写入日志文件。每一条记录都有自己的LSN(log sequence number, 表示从日志记录创建开始到特定的日志记录已经写入的字节数)。每个日志块包含一个日志头段(12字节)、一个尾段(4字节),以及一组日志记录(512 – 12 – 4 = 496字节) 。

Redo 日志块结构

首先看下日志块头结构。
1) log block number字段:占用日志块最开始的4个字节表示这是第几个block块。 其是通过LSN计算得来,计算的函数是log_block_convert_lsn_to_no();
2) block data len 字段:两个字节表示该block中已经有多少个字节被使用; 若是整个块都写满了日志的话它的长度就应该是(OS_FILE_LOG_BLOCK_SIZE) 512 字节。
3) First Record offset 字段:占用两个字节,表示该block中作为第一个新的mtr开始log record的偏移量。log_block_get_first_rec_group()就是用保存在这个字段的值,获取到此块中第一个新的mtr开始的日志位置。
4) 中间496字节存放真正的Redo日志。
5) Checksum字段:是块的尾,占用四个字节,表示此log block计算出的校验值,用于正确性校验。

LSN和文件偏移量(offset)之间映射

在MySQL Innodb引擎中LSN是一个非常重要的概念,表示从日志记录创建开始到特定的日志记录已经写入的字节数,LSN的计算是包含每个BLOCK的头和尾字段的。那如何由一个给定LSN的日志,在日志文件中找到它存储的位置的偏移量并能正确的读出来呢。所有的日志文件要属于日志组,而在log_group_t里的lsn和lsn_offset字段已经记录了某个日志lsn和其存放在文件内的偏移量之间的对应关系。我们可以利用存储在group内的lsn和给定lsn之间的相对位置,来计算出给定lsn在文件中的存储位置。可以参考函数log_group_calc_lsn_offset()的实现。其核心代码实现如下:

    gr_lsn = group->lsn;

    gr_lsn_size_offset = log_group_calc_size_offset(group->lsn_offset, group);

    group_size = log_group_get_capacity(group);

    if (lsn >= gr_lsn) {

        difference = lsn - gr_lsn;
    } else {
        difference = gr_lsn - lsn;

        difference = difference % group_size;

        difference = group_size - difference;
    }

    offset = (gr_lsn_size_offset + difference) % group_size;

    /* fprintf(stderr,
    "Offset is " LSN_PF " gr_lsn_offset is " LSN_PF
    " difference is " LSN_PF "\n",
    offset, gr_lsn_size_offset, difference);
    */

    return(log_group_calc_real_offset(offset, group));

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
8月前
|
SQL 监控 关系型数据库
MySQL事务处理:ACID特性与实战应用
本文深入解析了MySQL事务处理机制及ACID特性,通过银行转账、批量操作等实际案例展示了事务的应用技巧,并提供了性能优化方案。内容涵盖事务操作、一致性保障、并发控制、持久性机制、分布式事务及最佳实践,助力开发者构建高可靠数据库系统。
|
数据可视化 项目管理 Android开发
从计划到完成:最佳Todolist任务管理软件全指南
在快节奏的工作环境中,高效的任务管理软件成为提升生产力的关键。本文深入评测了几款高人气的Todolist工具,包括板栗看板、Todoist、TickTick、Microsoft To-Do和Trello,从功能、易用性、优缺点等方面进行全面对比,帮助用户根据实际需求选择最适合的任务管理工具。
2646 3
|
Oracle 关系型数据库 数据管理
【赵渝强老师】Oracle数据库的闪回技术
在Oracle数据库操作中,难免会遇到误删表或提交错误事务等问题,可能导致数据丢失甚至数据库停止运行。传统解决方法依赖备份恢复,但需提前准备正确备份。为此,Oracle提供了闪回技术,无需备份即可快速恢复数据。它支持7种类型的操作,如闪回查询、版本查询、表恢复等,能有效应对逻辑损坏和用户错误。闪回技术基于还原(undo)数据管理,启用自动管理后可实现高效恢复。
415 0
|
数据采集 前端开发 测试技术
Selenium中定位元素的9种方法
在Selenium中,定位页面元素是自动化测试和网页爬虫的基础。常用的9种元素定位方法包括:ID、Name、Class Name、Tag Name、CSS Selector、XPath、Link Text、Partial Link Text,以及XPath和CSS选择器的组合使用。每种方法各有优劣,建议根据页面的具体情况和元素的属性选择最合适的方法,并使用显式等待确保元素可用。
2231 5
|
存储 SQL 关系型数据库
面试官:你能聊聊 binlog、undo log、redo log 吗?
本文详细解析了MySQL数据库中的三种日志:binlog、undo log和redo log。binlog用于记录数据库的所有表结构变更及数据修改,支持归档、主从复制和数据恢复;undo log用于事务回滚,确保事务的原子性和实现多版本控制;redo log则用于crash-safe,确保数据库异常重启后已提交记录不丢失。文章通过实例和图表,深入浅出地介绍了每种日志的特点、应用场景及其实现机制。适合数据库开发者和运维人员阅读。
1048 2
|
前端开发 JavaScript 数据库
Web的B/S架构
Web的B/S架构
2235 1
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的明水县苹果网吧计费管理系统附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的明水县苹果网吧计费管理系统附带文章和源代码部署视频讲解等
266 1
|
前端开发 Java
【十四】springboot整合WebSocket
【十四】springboot整合WebSocket
530 0
|
存储 JSON 算法
新手避坑:盘点使用ClickHouse最容易犯的12个错误
在这篇文章中,我们突出了新手用户遇到的最常见的12个问题,这些问题是由于在使用ClickHouse的过程中,不遵循最佳实践,甚至反最佳实践而导致的。对于每一个问题,我们都推荐了一个解决方案或正确的使用方法。
9171 18
新手避坑:盘点使用ClickHouse最容易犯的12个错误

相关产品

  • 云数据库 RDS MySQL 版