Mysql专栏 - redo log日志细节

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: redo log 日志在介绍整个innodb的存储引擎结构的时候进行过介绍,本节将会继续深入redo log了解内部的结构了解内部的基础存储结构,同时了解关于redo log写入到磁盘的时机,并且了解redo log的日志有几个

前言


本节讲述的是redolog日志,介绍redo log写磁盘的过程以及redo log的随机写和顺序写,最后我们讲介绍关于mysql最常见的事务问题,并且介绍mysql的事务隔离级别以及隔离级别的特性。


概述


redo log 日志在介绍整个innodb的存储引擎结构的时候进行过介绍,本节将会继续深入redo log了解内部的结构了解内部的基础存储结构,同时了解关于redo log写入到磁盘的时机,并且了解redo log的日志有几个,


为什么要引入redo log?


说白了是为了保证mysql宕机的时候,数据恢复可以按照顺序的恢复方式而不是随机读写,redo log也是保证事务一致性的关键组件。


Redo log写磁盘的过程


Redo log存放的内容


存放的内容如下:「表空间号+数据页号+偏移量+修改几个字节的值+具体的值」,为了使表示数据页的内容修改了几个字节的值, redo log使用了类型划分:


  1. Mlog_1byte:表示修改了1个字节
  2. Mlog_2byte:表示两个
  3. 以此类推的4字节和8字节
  4. 如果修改了很多:「mlog_write_string」


所以一条redo log的格式如下:



日志类型(就是类似MLOG_1BYTE之类的),表空间ID,数据页号,数据页中的偏移量,具体修改的数据



下面是对应的数据结构图:


image.png


Redo log block 存放数据页


Redo log**「不是」按照单行写入日志文件的,而是使用block来进行管理,一个redo log block 为512字节。内部包含了12字节的header块,496字节的body块,和4字节的trailer 块尾,而12个字节的数据头又包含了:「4个字节的块编号,2个字节写入的数据长度,2个字节第一个日志的分组偏移量,4个字节的check point no」**,最终他的数据结构如下


image.png


redolog行如何存储


在写入数据的时候,redo log一行日志是如下的形式进行写入的,由于redo log并不是单行存储,而是使用连续的512字节的block块进行存放的,当然这个操作是在内存中的redolog buffer中完成,当缓冲池中一个块被写满之后,是肯定需要刷入到磁盘的,所以此时会有一个后台线程不断的把数据写入到redo log的磁盘文件中,最终他的效果就如同下面这般:


上面我们介绍的redo log一行的存储结构,在这里就可以派上用场,redo log的行数据不断写入到body到数据块里面,并且后台线程不断的把数据刷新到磁盘当中,当一行数据的不断写入,到达一个block块的大小的时候,就需要把它写入到磁盘的文件里面,写入完成之后,内存完成操作,将会把数据写入到具体的磁盘对应的块里面也就是磁盘文件的内部。


image.png


redo log buffer存储redo log block


Redo log的数据和缓冲池一样也是使用缓存的方式刷入到磁盘的,redo log buffer会在mysql启动的时候申请一块连续的内存空间来存放 redo log block,他的格式如下所示:


image.png


我们可以设置参数:「innodb_log_buffer_size」 来指定redo log buffer的大小,默认值为16mb,这个大小足够大了,毕竟一个block为512字节,在执行大批量数据操作的时候,可能会出现多个redo log 为一组的情况,也就是数据跨越了多个redo log页进行存储。


Redo log 日志什么时候写入磁盘


关于这个内容我们需要了解下面两个问题:


  1. Redo log日志文件有几个?
  2. Redo log block什么时候会把数据刷入到磁盘?


刷新到磁盘的时机


mysql触发下面的条件的时候会把redo log buffer 刷新到磁盘当中:


  1. 超过redo log buffer 的一半大小
  2. Redo log需要在事务提交的时候,需要把redo log对应的redo log block刷新到磁盘中,同时为了保证事务正确提交,redo log存在重做日志。
  3. 后台线程1秒一次刷新数据到磁盘
  4. mysql关闭会把redo log 全部刷新到磁盘


这里需要记住一个重点:「只有在redo log 的内容刷新到磁盘,事务提交才算是成功,只有这样才能算是事务的正确」


实际上默认情况下redo log都会写入一个目录中的文件里,这个目录可以通过show variables like 'datadir'来查看,可以通过**「innodb_log_group_home_dir」**参数来设置这个 目录的。


Redo log日志文件有几个


redo log是有多个的,写满了一个就会写下一个redo log,而且可以限制redo log文件的数量,通过**「innodb_log_file_size」可以指定每个redo log文件的大小,默认是「48MB」**,通过 **「innodb_log_files_in_group」**可以指定日志文件的数量,默认就2个,也就是96MB,可能看上去很小,但是实际上这个文件数量存个百万千万的数据完全不是问题。


所以在上面提到的目录中里就两个日志文件,分别为**「ib_logfile0」「ib_logfile1」**,每个48MB,最多就这2个日志文件,就是先写第一个,写满了写第二个,那第二个写满了怎么办?继续回去写第一个即可。


如果不想使用默认的大小如何处理呢,其实调节上述两个参数就可以了,比如每个redo log文件是96MB, 最多保留100个redo log文件等等。


Undo log配合 redo log进行日志回滚


Undo log需要配合redo log进行下面的记录操作:


  • 删除需要把删除之前的数据插入回去
  • 更新需要旧值更新回去
  • 新增需要把新增之后的数据删除掉


最终undo log日志的结构如下:


image.png


Redo log并发问题


多个事务并发执行的时候,可能会同时对缓存页里的一行数据进行更新,这个冲突怎么处理?是否要加锁?可能有的事务在对一行数据做更新,有的事务在查询这行数据,这里的冲突怎么处理?


脏写、脏读、不可重复读、幻读(重点)


1. 脏写


根据下面的图我们说下脏写,当事务A更新一行事务B准备更新的数据,在事务A更新之后事务B执行了更新操作,然后A更新完成之后却回滚了,并且在B更新之后把值改了回去。这样的操作结果就是:「B操作完结果却是NULL」,本质就是事务B更新了一个事务A操作过的数据,结果事务A没有提交,但是一旦更新会随时影响事务B的操作结果。


image.png


2. 脏读


用最简单的话其实就是一个事务读到了一个未提交的值,而一旦这个值失效就会出现业务的问题。


其实一句话总结,无论是脏写还是脏读,都是因为一个事务去更新或者查询了另外一个还没提交的事务 更新过的数据。因为另外一个事务还没提交,所以他随时可能会反悔会回滚,那么必然导致你更新的数据就没了,或者你之前查询到的数据就没了,这就是脏写和脏读两种坑爹场景。


3. 不可重复读:


不可重复读:在第一次进行查询的时候没有任何干扰


image.png


事务B进行更新+提交事务,同时修改一个值,然而A再去读和上一次不一样了


image.png


然后C也插进来,又把这个值给更新了,然后A又去读了一次,又发现不一样了


image.png


不可重复读并不是严重的问题,但是取决于数据库如何设计,因为重复读取一个值发生改变或者不改变要根据数据库的设计者来决定。


这里有两种方案:


  • A事务读取之后,除非他提交事务,否则BC不能做任何更改,或者A读取一次之后就不会再读取第二次,或者多次读取的值都是相同的,也称为不可重复读
  • 可重复读就是上面图表的情况。


4. 幻读


幻读指的就是你一个事务用一样的SQL多次查询,结果每次查询都会发现查到了一些之前没看到过的数据,幻读就是读到了别人没有提交过的数据。



「不可重复读和幻读到底有什么区别呢?」


(1) 不可重复读是读取了其他事务更改的数据,「针对update操作」


解决:使用行级锁,锁定该行,事务A多次读取操作完成后才释放该锁,这个时候才允许其他事务更改刚才的数据。


(2) 幻读是读取了其他事务新增的数据,「针对insert和delete操作」


解决:使用表级锁,锁定整张表,事务A多次读取数据总量之后才释放该锁,这个时候才允许其他事务新增数据。


这时候再理解事务隔离级别就简单多了呢。



mysql的四种隔离级别:


  • read uncommitted(读未提交)
  • read committed(读已提交)
  • repeatable read(可重复读)
  • serializable(串行化)


隔离级别的特性:


  1. 读未提交:不允许脏写发生。其实就是说可以防止两个线程同时更新一个值。但是不防其他任何内容
  2. 读已提交:不允许脏写和脏读,也是即可防止两个线程同时更新一个值,又可以防止两个值同时读同一个值,也就是一个值肯定读不到另一个未提交的事务改动的数据情况。但是可能会多次读到一个值被提交到事务不断改动的情况
  3. 不可重复读:也就是可以防止脏写、脏读、不可重复读这三个层级在Mysql中的体现就是,同一个事务无论读多少次都不会读到已经提交的业务。但是会出现读取到其他事务新增或者删除的数据
  4. 串行化:完全同步,每次操作都只允许一个线程访问


总结


本节深入了redo log的内部细节,并且简单介绍了undo log是如何配合redo log进行回滚操作的,以及事务的ACID特性的细节内容,最终我们简单回顾了mysql的四种隔离级别以及对应的问题。


写在最后


可以看到redo log的内容结构还是有些复杂的,但是我们只需要基础了解即可,如果需要继续深入需要更多的阅读源代码并且进行总结和消化。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
486 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
25天前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
|
3天前
|
SQL 关系型数据库 MySQL
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
MySQL事务日志-Undo Log工作原理分析
|
15天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
42 3
|
1月前
|
存储 监控 安全
什么是事件日志管理系统?事件日志管理系统有哪些用处?
事件日志管理系统是IT安全的重要工具,用于集中收集、分析和解释来自组织IT基础设施各组件的事件日志,如防火墙、路由器、交换机等,帮助提升网络安全、实现主动威胁检测和促进合规性。系统支持多种日志类型,包括Windows事件日志、Syslog日志和应用程序日志,通过实时监测、告警及可视化分析,为企业提供强大的安全保障。然而,实施过程中也面临数据量大、日志管理和分析复杂等挑战。EventLog Analyzer作为一款高效工具,不仅提供实时监测与告警、可视化分析和报告功能,还支持多种合规性报告,帮助企业克服挑战,提升网络安全水平。
|
2月前
|
存储 监控 安全
什么是日志管理,如何进行日志管理?
日志管理是对IT系统生成的日志数据进行收集、存储、分析和处理的实践,对维护系统健康、确保安全及获取运营智能至关重要。本文介绍了日志管理的基本概念、常见挑战、工具的主要功能及选择解决方案的方法,强调了定义管理目标、日志收集与分析、警报和报告、持续改进等关键步骤,以及如何应对数据量大、安全问题、警报疲劳等挑战,最终实现日志数据的有效管理和利用。
154 0
|
15天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
39 3
|
15天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
57 2
|
28天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
190 15
|
22天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。

推荐镜像

更多