redo log-Transaction(2)—mysql进阶(六十)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: redo log-Transaction(2)—mysql进阶(六十)

前面我们说了为了吧buffer pool的数据持久化到磁盘上,比如修改了一条数据,不可能每次吧整个页的数据都刷新过去,这样耗费性能,innoDB就是把修改的数据记录在redo日志里,redo日志格式主要是spaceId,type,page_number,offset,Data等。Offset记录上一条数据的地址,为了修改上一条记录头部新的next record,data记录的就是真实数据。Redo日志主要关注的就是一条语句修改了多少b+树,针对其中某颗树,可能增加了页,也可能更新了叶子节点或者内节点。他会记录修改日志或者删除日志,而删除日志格式又会分为开始和结束,MLOG_COMP_LIST_START_DELETE和MLOG_COMP_LIST_END_DELETE。

redo log(1)—mysql进阶(五十九)


Mini-transaction


以组的形式写入redo日志

一个sql语句可能修改若干个页面,比如我们前面说的一条insert语句可能修改系统表空间页号为7 页面的max row id属性,还会更新b+树聚簇索引和二级索引对应的页面。由于这些都是发生在buffer pool里,这时候都需要记录在redo日志里,于是在记录的时候,innoDB又把这些分为不同的组。

修改max row_id是不可分割的,向聚簇索引对应的b+树插入一条记录产生的redo日志不可分割,向某个二级索引b+树插入一条记录产生的redo日志不可分割,还有一些其他页面生成的redo日志不可分割。。。

怎么理解不可分割呢,我们向某个索引对应的b+树插入一记录,在插入b+树之前,需要定位向哪个叶子节点代表的数据页,定位到具体的数据页后,有两种可能:

情况一:该数据页的剩余空闲空间充足,足够容纳这一条待插记录,这种就很简单,直接把记录插入这个数据页,记录一条MLOG_COMP_REC_INSERT记录到redo日志,我们吧这种情况称为乐观插入。

情况二:该数据页的剩余空间不足,那么这时候就需要进行所谓的页分裂操作,也就是新建一个叶子节点,插入一条10的记录,那么比10大的记录都会移到新建的叶子节点,吧10插到前面的叶子节点,如果内节点不够用,则同样也需要分裂,这样会记录更多的redo日志,我们称这种为悲观插入。对于这些,我们还需要修改各种段,区的统计信息,各种链表的统计信息,(比如free链表,fsp_free_page链表等等),反正有二三十条记录。

这些操作肯定必须是原子性的,比如不能在系统宕机的时候,redo日志吧聚簇索引的修改记录恢复,而二级索引的修改记录未恢复,这种必定导致数据错误,形成不完成的b+树。如何保证原子性呢,于是innoDB规定这些操作必须以【组】的形式来记录到redo日志,在系统宕机重启时候,要么全部一起恢复,要么一条都不恢复。那么怎么做到呢:

当悲观插入,需要记录多条redo日志。innoDB解决办法是,每次一组日志之后,记录一条特殊的redo日志,MLOG_MULTI_REC_END,type字段对应的十进制数字为31,该类型的结构很简单,只有一个type字段。所以当系统崩溃时候,只有解析到MLOG_MULTI_REC_END才会算是一组完整的操作,如果没有解析到MLOG_MULTI_REC_END,则之前解析的都放弃。

如果有的操作只记录一条数据,然后海特意记录一条MLOG_MULTI_REC_END,不是很浪费吗,这时候如果type字段的第一个比特位是1,代表需要该原子性操作只需要操作一条redo日志。


Redo日志写入过程


Redo log block

innoDB为了更好的进行系统恢复,他们吧通过mtr生成的redo日志都放在大小为512个字节的页中,为了和我们前面表空间的数据页做区别,所以redo日志的页我们称为block(其实他们是差不多的)。Redo log block的结构如下,

log block header:12个字节。

Log block body:496个字节。

Log block trailer:4个字节。

其中redo日志主要存储在body里,我们在看看header 和trailer

Log block header 分为四个属性:

log_block_hdr_no:4个字节,每个block都有一个大于0的唯一标号,本属性就代表唯一值。

log_block_hdr_data_len:表示已经存入redo日志已经使用的字节,从12个字节开始,因为log block body是从12个字节处开始,如果log block body全部填满了,则记录是512字节。

log_block_first_rec_group:多条redo日志会生成一个记录组redo_log_record_group,这个log_block_first_rec_group就代表mtr生成redo日志记录组的偏移量。

log_block_checkpoint_no:表示所谓checkpoint的序号,后面着重介绍。

Log block trailer分为一个属性:

Log_block_checksum:表示block的效验值,用于正确性效验。


Redo日志缓冲区


我们前面说过,为了存储数据到磁盘,会有一个数据的缓冲区buffer pool,同理,redo日志也不能直接写到磁盘,而是需要在mysql启动前,申请一个redo log buffer的连续内存空间(redo日志缓冲区),可以称为log buffer,这篇区域划分为若干个redo log buffer。

可以通过设置启动参数innoDB_log_buffer_size来制定log_buffer的大小,在mysql5.7.21这个版本,默认参数是12mb。


Redo日志写入log buffer


向log buffer 写入redo日志是顺序的,先往前面的block中写,当前面的block满了之后,就往后面空的写,所以如何定位到空的block呢,第一个问题就是block的偏移量,所以innoDB提供了一个buf_free的全局变量来记录block的偏移量,指明redo日志写入的位子。

我们前面说了一个mtr执行过程中可能产生若干条redo日志,这些日志都是不可分割的组,所以并不是每生成一条redo日志,就将其插入log buffer中,而是将mtr产生的日志先存到一个地方,当mtr结束的时候,再将产生的一组数据全部赋值到log_buffer中。

假设我们现在有两个名为T1/T2的事务,每个事务包含两个mtr,我们给mtr命名一下:

事务T1的两个mtr分别为mtr_t1_1和mtr_t1_2。

事务T2的两个mtr分别为mtr_t2_1和mtr_t2_2。

不同的事务可能并发执行,所以T1和T2的mtr可能交替执行,每当一个mtr执行完毕,伴随着该mtr生成的一组redo日志就需要复制到log buffer 中,也就是说不同事务的mtr可能是交替写入log buffer中的。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5月前
|
存储 SQL 关系型数据库
MySQL语句详解:从基础到进阶的全面指南
MySQL语句详解:从基础到进阶的全面指南
|
2月前
|
SQL 存储 关系型数据库
美团面试:binlog、redo log、undo log的底层原理是什么?它们分别实现ACID的哪个特性?
老架构师尼恩在其读者交流群中分享了关于 MySQL 中 redo log、undo log 和 binlog 的面试题及其答案。这些问题涵盖了事务的 ACID 特性、日志的一致性问题、SQL 语句的执行流程等。尼恩详细解释了这些日志的作用、所在架构层级、日志形式、缓存机制以及写文件方式等内容。他还提供了多个面试题的详细解答,帮助读者系统化地掌握这些知识点,提升面试表现。此外,尼恩还推荐了《尼恩Java面试宝典PDF》和其他技术圣经系列PDF,帮助读者进一步巩固知识,实现“offer自由”。
美团面试:binlog、redo log、undo log的底层原理是什么?它们分别实现ACID的哪个特性?
|
2月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1695 14
|
2月前
|
存储 关系型数据库 MySQL
MySQL中的Redo Log、Undo Log和Binlog:深入解析
【10月更文挑战第21天】在数据库管理系统中,日志是保障数据一致性和完整性的关键机制。MySQL作为一种广泛使用的关系型数据库管理系统,提供了多种日志类型来满足不同的需求。本文将详细介绍MySQL中的Redo Log、Undo Log和Binlog,从背景、业务场景、功能、底层实现原理、使用措施等方面进行详细分析,并通过Java代码示例展示如何与这些日志进行交互。
209 0
|
3月前
|
存储 缓存 关系型数据库
redo log 原理解析
redo log 原理解析
51 0
redo log 原理解析
|
4月前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
203 0
|
4月前
|
存储 关系型数据库 MySQL
深入MySQL:事务日志redo log详解与实践
【8月更文挑战第24天】在MySQL的InnoDB存储引擎中,为确保事务的持久性和数据一致性,采用了redo log(重做日志)机制。redo log记录了所有数据修改,在系统崩溃后可通过它恢复未完成的事务。它由内存中的redo log buffer和磁盘上的redo log file组成。事务修改先写入buffer,再异步刷新至磁盘,最后提交事务。若系统崩溃,InnoDB通过redo log重放已提交事务并利用undo log回滚未提交事务,确保数据完整。理解redo log工作流程有助于优化数据库性能和确保数据安全。
658 0
|
5月前
|
关系型数据库 分布式数据库 数据库
PolarDB产品使用问题之如何设置Redo日志保存时间
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
5月前
|
存储 关系型数据库 MySQL
MySQL数据库开发进阶:精通数据库表的创建与管理22
【7月更文挑战第22天】数据库的创建与删除,数据表的创建与管理
52 1
|
5月前
|
存储 关系型数据库 MySQL
MySQL系列: undo和redo工作原理
MySQL系列: undo和redo工作原理
176 1
下一篇
DataWorks