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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介:

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 
相关文章
|
3月前
|
存储 关系型数据库 MySQL
介绍MySQL的InnoDB引擎特性
总结而言 , Inno DB 引搞 是 MySQL 中 高 性 能 , 高 可靠 的 存 储选项 , 宽泛 应用于要求强 复杂交易处理场景 。
142 15
|
8月前
|
存储 网络协议 关系型数据库
MySQL8.4创建keyring给InnoDB表进行静态数据加密
MySQL8.4创建keyring给InnoDB表进行静态数据加密
258 1
|
7月前
|
存储 SQL 关系型数据库
MySQL存储引擎简介
在选择相应的存储引擎时,需要充分考虑实际业务场景、性能需求和数据一致性要求,从而为数据管理提供最佳支持。
386 17
|
8月前
|
SQL 缓存 关系型数据库
使用温InnoDB缓冲池启动MySQL测试
使用温InnoDB缓冲池启动MySQL测试
147 0
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
3694 31
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
7月前
|
监控 容灾 算法
阿里云 SLS 多云日志接入最佳实践:链路、成本与高可用性优化
本文探讨了如何高效、经济且可靠地将海外应用与基础设施日志统一采集至阿里云日志服务(SLS),解决全球化业务扩展中的关键挑战。重点介绍了高性能日志采集Agent(iLogtail/LoongCollector)在海外场景的应用,推荐使用LoongCollector以获得更优的稳定性和网络容错能力。同时分析了多种网络接入方案,包括公网直连、全球加速优化、阿里云内网及专线/CEN/VPN接入等,并提供了成本优化策略和多目标发送配置指导,帮助企业构建稳定、低成本、高可用的全球日志系统。
817 54
|
12月前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
351 9
|
10月前
|
存储 SQL 关系型数据库
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log、原理、写入过程;binlog与redolog区别、update语句的执行流程、两阶段提交、主从复制、三种日志的使用场景;查询日志、慢查询日志、错误日志等其他几类日志
801 35
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
|
10月前
|
存储 缓存 关系型数据库
图解MySQL【日志】——Redo Log
Redo Log(重做日志)是数据库中用于记录数据页修改的物理日志,确保事务的持久性和一致性。其主要作用包括崩溃恢复、提高性能和保证事务一致性。Redo Log 通过先写日志的方式,在内存中缓存修改操作,并在适当时候刷入磁盘,减少随机写入带来的性能损耗。WAL(Write-Ahead Logging)技术的核心思想是先将修改操作记录到日志文件中,再择机写入磁盘,从而实现高效且安全的数据持久化。Redo Log 的持久化过程涉及 Redo Log Buffer 和不同刷盘时机的控制参数(如 `innodb_flush_log_at_trx_commit`),以平衡性能与数据安全性。
462 5
图解MySQL【日志】——Redo Log

推荐镜像

更多