大厂基本功 | MySQL 三大日志 ( binlog、redo log 和 undo log ) 的作用?

前言

MySQL日志 主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中,比较重要的还要属二进制日志binlog(归档日志)和事务日志redo log(重做日志)和undo log(回滚日志)。

 今天就来聊聊redo log(重做日志)、binlog(归档日志)、两阶段提交、undo log(回滚日志)。

redo log

redo log(重做日志)是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力。

比如MySQL实例挂了或宕机了,重启时,InnoDB存储引擎会使用redo log恢复数据,保证数据的持久性与完整性。

MySQL中数据是以页为单位,你查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到Buffer Pool中。

后续的查询都是先从Buffer Pool中找,没有命中再去硬盘加载,减少硬盘IO开销,提升性能。

更新表数据的时候,也是如此,发现Buffer Pool里存在要更新的数据,就直接在Buffer Pool里更新。

然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(redo log buffer)里,接着刷盘到redo log文件里。

理想情况,事务一提交就会进行刷盘操作,但实际上,刷盘的时机是根据策略来进行的。

小贴士:每条 redo 记录由“表空间号+数据页号+偏移量+修改数据长度+具体修改的数据”组成

刷盘时机

InnoDB存储引擎为redo log的刷盘策略提供了innodb_flush_log_at_trx_commit参数,它支持三种策略:

  • 0:设置为 0 的时候,表示每次事务提交时不进行刷盘操作

  • 1:设置为 1 的时候,表示每次事务提交时都将进行刷盘操作(默认值)

  • 2:设置为 2 的时候,表示每次事务提交时都只把 redo log buffer 内容写入 page cache

innodb_flush_log_at_trx_commit参数默认为 1 ,也就是说当事务提交时会调用fsync对 redo log 进行刷盘

另外,InnoDB存储引擎有一个后台线程,每隔1秒,就会把redo log buffer中的内容写到文件系统缓存(page cache),然后调用fsync刷盘。

也就是说,一个没有提交事务的redo log记录,也可能会刷盘。

为什么呢?

因为在事务执行过程redo log记录是会写入redo log buffer中,这些redo log记录会被后台线程刷盘。

除了后台线程每秒1次的轮询操作,还有一种情况,当redo log buffer占用的空间即将达到innodb_log_buffer_size一半的时候,后台线程会主动刷盘。

下面是不同刷盘策略的流程图。

innodb_flush_log_at_trx_commit=0

0时,如果MySQL挂了或宕机可能会有1秒数据的丢失。

innodb_flush_log_at_trx_commit=1

1时, 只要事务提交成功,redo log记录就一定在硬盘里,不会有任何数据丢失。

如果事务执行期间MySQL挂了或宕机,这部分日志丢了,但是事务并没有提交,所以日志丢了也不会有损失。

innodb_flush_log_at_trx_commit=2

2时, 只要事务提交成功,redo log buffer中的内容只写入文件系统缓存(page cache)。

如果仅仅只是MySQL挂了不会有任何数据丢失,但是宕机可能会有1秒数据的丢失。

日志文件组

硬盘上存储的redo log日志文件不只一个,而是以一个日志文件组的形式出现的,每个的redo日志文件大小都是一样的。

比如可以配置为一组4个文件,每个文件的大小是1GB,整个redo log日志文件组可以记录4G的内容。

它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写,如下图所示。

在个日志文件组中还有两个重要的属性,分别是write pos、checkpoint

  • write pos是当前记录的位置,一边写一边后移

  • checkpoint是当前要擦除的位置,也是往后推移

每次刷盘redo log记录到日志文件组中,write pos位置就会后移更新。

每次MySQL加载日志文件组恢复数据时,会清空加载过的redo log记录,并把checkpoint后移更新。

write poscheckpoint之间的还空着的部分可以用来写入新的redo log记录。

如果write pos追上checkpoint,表示日志文件组满了,这时候不能再写入新的redo log记录,MySQL得停下来,清空一些记录,把checkpoint推进一下。

redo log 小结

相信大家都知道redo log的作用和它的刷盘时机、存储形式。

现在我们来思考一个问题:只要每次把修改后的数据页直接刷盘不就好了,还有redo log什么事?

它们不都是刷盘么?差别在哪里?

1Byte=8bit 1KB=1024Byte 1MB=1024KB 1GB=1024MB 1TB=1024GB

实际上,数据页大小是16KB,刷盘比较耗时,可能就修改了数据页里的几Byte数据,有必要把完整的数据页刷盘吗?

而且数据页刷盘是随机写,因为一个数据页对应的位置可能在硬盘文件的随机位置,所以性能是很差。

如果是写redo log,一行记录可能就占几十Byte,只包含表空间号、数据页号、磁盘文件偏移 量、更新值,再加上是顺序写,所以刷盘速度很快。

所以用redo log形式记录修改内容,性能会远远超过刷数据页的方式,这也让数据库的并发能力更强。

其实内存的数据页在一定时机也会刷盘,我们把这称为页合并,讲Buffer Pool的时候会对这块细说

binlog

redo log它是物理日志,记录内容是“在某个数据页上做了什么修改”,属于InnoDB存储引擎。

binlog是逻辑日志,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”,属于MySQL Server层。

不管用什么存储引擎,只要发生了表数据更新,都会产生binlog日志。

binlog到底是用来干嘛的?

可以说MySQL数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据一致性。

binlog会记录所有涉及更新数据的逻辑操作,并且是顺序写。

记录格式

binlog日志有三种格式,可以通过binlog_format参数指定。

  • statement

  • row

  • mixed

指定statement,记录的内容是SQL语句原文,比如执行一条update T set update_time=now() where id=1,记录的内容如下。

同步数据时,会执行记录的SQL语句,但是有个问题,update_time=now()这里会获取当前系统

时间,直接执行会导致与原库的数据不一致。

为了解决这种问题,我们需要指定为row,记录的内容不再是简单的SQL语句了,还包含操作的具体数据,记录内容如下。

row格式记录的内容看不到详细信息,要通过mysqlbinlog工具解析出来。

update_time=now()变成了具体的时间update_time=1627112756247,条件后面的@1、@2、@3 都是该行数据第 1 个~3 个字段的原始值(假设这张表只有 3 个字段)。

这样就能保证同步数据的一致性,通常情况下都是指定为row,这样可以为数据库的恢复与同步带来更好的可靠性。

但是这种格式,需要更大的容量来记录,比较占用空间,恢复与同步时会更消耗IO资源,影响执行速度。

所以就有了一种折中的方案,指定为mixed,记录的内容是前两者的混合。

MySQL会判断这条SQL语句是否可能引起数据不一致,如果是,就用row格式,否则就用statement格式。

写入机制

binlog的写入时机也非常简单,事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。

因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache

我们可以通过binlog_cache_size参数控制单个线程 binlog cache 大小,如果存储内容超过了这个参数,就要暂存到磁盘(Swap)。

binlog日志刷盘流程如下

  • 上图的 write,是指把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快

  • 上图的 fsync,才是将数据持久化到磁盘的操作

writefsync的时机,可以由参数sync_binlog控制,默认是0

0的时候,表示每次提交事务都只write,由系统自行判断什么时候执行fsync

虽然性能得到提升,但是机器宕机,page cache里面的 binglog 会丢失。

为了安全起见,可以设置为1,表示每次提交事务都会执行fsync,就如同binlog 日志刷盘流程一样。

最后还有一种折中方式,可以设置为N(N>1),表示每次提交事务都write,但累积N个事务后才fsync

在出现IO瓶颈的场景里,将sync_binlog设置成一个比较大的值,可以提升性能。

同样的,如果机器宕机,会丢失最近N个事务的binlog日志。

两阶段提交

redo log(重做日志)让InnoDB存储引擎拥有了崩溃恢复能力。

binlog(归档日志)保证了MySQL集群架构的数据一致性。

虽然它们都属于持久化的保证,但是则重点不同。

在执行更新语句过程,会记录redo logbinlog两块日志,以基本的事务为单位,redo log在事务执行过程中可以不断写入,而binlog只有在提交事务时才写入,所以redo logbinlog的写入时机不一样。

回到正题,redo logbinlog两份日志之间的逻辑不一致,会出现什么问题?

我们以update语句为例,假设id=2的记录,字段c值是0,把字段c值更新成1SQL语句为update T set c=1 where id=2

假设执行过程中写完redo log日志后,binlog日志写期间发生了异常,会出现什么情况呢?

由于binlog没写完就异常,这时候binlog里面没有对应的修改记录。因此,之后用binlog日志恢复数据时,就会少这一次更新,恢复出来的这一行c值是0,而原库因为redo log日志恢复,这一行c值是1,最终数据不一致。

为了解决两份日志之间的逻辑一致问题,InnoDB存储引擎使用两阶段提交方案。

原理很简单,将redo log的写入拆成了两个步骤preparecommit,这就是两阶段提交

使用两阶段提交后,写入binlog时发生异常也不会有影响,因为MySQL根据redo log日志恢复数据时,发现redo log还处于prepare阶段,并且没有对应binlog日志,就会回滚该事务。

再看一个场景,redo log设置commit阶段发生异常,那会不会回滚事务呢?

并不会回滚事务,它会执行上图框住的逻辑,虽然redo log是处于prepare阶段,但是能通过事务id找到对应的binlog日志,所以MySQL认为是完整的,就会提交事务恢复数据。

undo log

数据库事务四大特性中有一个是原子性,具体来说就是原子性是指对数据库的一系列操作,要么全部成功,要么全部失败,不可能出现部分成功的情况

我们知道如果想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行回滚,在 MySQL 中,恢复机制是通过回滚日志(undo log)实现的,所有事务进行的修改都会先先记录到这个回滚日志中,然后再执行相关的操作。

如果执行过程中遇到异常的话,我们直接利用回滚日志中的信息将数据回滚到修改之前的样子即可!并且,回滚日志会先于数据持久化到磁盘上。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务。

另外,MVCC的实现依赖于:隐藏字段、Read View、undo log。在内部实现中,InnoDB通过数据行的DB_TRX_IDRead View来判断数据的可见性,如不可见,则通过数据行的DB_ROLL_PTR找到undo log中的历史版本。

每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建Read View之前已经提交的修改和该事务本身做的修改。

总结

MySQL InnoDB 引擎使用redo log(重做日志)保证事务的持久性,使用undo log(回滚日志)来保证事务的原子性

MySQL数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据一致性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58782.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【系统架构设计师(第2版)】五、软件工程基础知识

5.1 软件工程 20世纪60年代,为了解决软件危机,提出了软件工程的概念。 软件危机的具体表现: 软件开发进度难以预测;软件开发成本难以控制;软件功能难以满足用户期望;软件质量无法保证;软件难以…

手机内卷下一站,AI Agent

作者 | 辰纹 来源 | 洞见新研社 2024年除夕夜,OPPO在央视春晚即将开始前举办了一场“史上最短发布会”,OPPO首席产品官刘作虎宣布,“OPPO正式进入AI手机时代”。 春节假期刚过,魅族又公开表示,将停止“传统智能手机…

科研绘图系列:R语言组合堆积图(stacked plot)

文章目录 介绍加载R包数据数据预处理画图1画图2组合图形系统信息介绍 堆积图(Stacked Chart),也称为堆叠图,是一种常用的数据可视化图表,主要用于展示不同类别的数据量在总体中的分布情况。堆积图可以是柱状图、条形图或面积图的形式,其中各个类别的数据量被叠加在一起,…

Node.js 完全教程:从入门到精通

Node.js 完全教程:从入门到精通 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,允许开发者在服务器端使用 JavaScript。它的非阻塞 I/O 和事件驱动架构使得 Node.js 非常适合于构建高性能的网络应用。本文将详细介绍 Node.js 的安装、基本语…

微服务day03

导入黑马商城项目 创建Mysql服务 由于已有相关项目则要关闭DockerComponent中的已开启的项目 [rootserver02 ~]# docker compose down WARN[0000] /root/docker-compose.yml: version is obsolete [] Running 4/4✔ Container nginx Removed …

每日一题之二叉树

已知结点元素值为正整数且值不相同的一棵二叉树。 该二叉树通过给出其先序遍历序列和中序遍历序列构造而成。 输入一个整数x,针对此二叉树编写程序求出x的右子树中所有结点值的和(若x不在树上,输出-1)。 输入说明:第一…

win10系统使用Visual Studio 2019或cmake编译SDL2为32位库时出现error C2118: 负下标winnt.h的解决方法

提示: 下图蓝体字中的VS2008是错误的,其实SDL.sln是用VS2010版本的软件开发的(对于SDL-release-2.0.5.zip源码而言至少是这样,而2024-11-6为止SDL是2.30.9版本了,2.30.9版本则无需自己编译,只需下载带后缀…

推荐一款管道数据检索工具:Pipedata-Pro

Pipedata-Pro是一款专为设计石油、天然气、水和蒸汽管道及管道系统的工程师开发的应用程序。该应用程序提供了设计管道系统所需的工程数据,拥有一个全面的管道类型、配件和材料数据库。 软件特点: 1. 技术参数查询:Pipedata-Pro 提供关于管道…

算法竞赛(Python)-数组

文章目录 一 、排序算法二 、二分查找1 二分查找讲解2 二分查找题目(1)二分查找(2)在排序数组中查找元素的第一个和最后一个位置(3)两数之和 II - 输入有序数组 三、数组双指针1对撞指针对撞指针题目1&…

基于STM32的LCD1602显示Proteus仿真设计(仿真+程序+设计报告+讲解视频)

这里写目录标题 1.主要功能0. 资料清单&下载链接资料下载链接:2.仿真设计3. 程序设计4. 设计报告5. 框图 基于STM32的LCD1602显示Proteus仿真设计(仿真程序设计报告讲解视频) 仿真图proteus 8.9 程序编译器:keil 5 编程语言&#xff1a…

SpringBoot项目编译报错 类文件具有错误的版本 61.0, 应为 52.0

springboot项目在编译时报错: /Users/Apple/Developer/art/caicai/cai-api/dubbo-samples/1-basic/dubbo-samples-spring-boot/dubbo-samples-spring-boot-provider/src/main/java/org/apache/dubbo/springboot/demo/provider/ProviderApplication.java:22:32 java…

PVE纵览-备份与快照指南

PVE纵览-备份与快照指南 文章目录 PVE纵览-备份与快照指南摘要1 备份与快照概述定义与区别备份与快照在PVE中的应用场景 2 PVE 备份功能详解备份类型与策略配置备份任务自动化备份管理 3 PVE 快照功能详解快照的工作原理快照的创建与恢复机制快照对系统性能的影响快照的使用场景…

Mac如何实现最简单的随时监测实时运行状态的方法

Mac book有着不同于Windows的设计逻辑与交互设计,使得Mac book有着非常棒的使用体验,但是在Mac电脑的使用时间过长时,电脑也会出现响应速度变慢或应用程序崩溃的情况,当发生的时候却不知道什么原因导致的,想要查询电脑…

JavaWeb合集23-文件上传

二十三 、 文件上传 实现效果&#xff1a;用户点击上传按钮、选择上传的头像&#xff0c;确定自动上传&#xff0c;将上传的文件保存到指定的目录中&#xff0c;并重新命名&#xff0c;生成访问链接&#xff0c;返回给前端进行回显。 1、前端实现 vue3AntDesignVue实现 <tem…

WPF之iconfont(字体图标)使用

1&#xff0c;前文&#xff1a; WPF的Xaml是与前端的Html有着高度相似性的标记语言&#xff0c;所以Xaml也可同Html一般轻松使用阿里提供的海量字体图标&#xff0c;从而有效的减少开发工作度。 2&#xff0c;下载字体图标&#xff1a; 登录阿里图标库网iconfont-阿里巴巴矢量…

leetcode92:反转链表||

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a;[1,4,3,2…

Python-安装与PyCharm的安装配置(1)

目录 安装 打开运行 PyCharm的安装 新建项目 安装 找到官网下载对应的电脑对应的版本 Welcome to Python.org -- 官网 下载稳定版的 安装记得勾选配置环境&#xff0c;这样自己就不需要再配置环境了 安装成功 至此python的运行环境就安装好了 打开运行 在开始菜单中可以…

python的编程基础分支,循环与函数的应用知识

编程基础是学习任何编程语言的必备知识之一。在Python中&#xff0c;分支、循环和函数是常用的编程概念&#xff0c;它们可以让我们编写出更复杂、更灵活的程序。 分支 分支是根据条件来决定程序执行的不同路径。在Python中&#xff0c;我们使用if语句来实现分支。 if 条件:# …

qt QLocale详解

1、概述 QLocale是Qt框架中的一个类&#xff0c;用于处理与本地化相关的操作。它能够方便地实现日期、时间、数字和货币的格式化和解析&#xff0c;支持不同的语言、区域设置和字符集。QLocale提供了一种跨平台的方式来获取当前系统的语言设置&#xff0c;并返回该语言的本地化…

缓存、注解、分页

一.缓存 作用&#xff1a;应用查询上&#xff0c;内存中的块区域。 缓存查询结果&#xff0c;减少与数据库的交互&#xff0c;从而提高运行效率。 1.SqlSession 缓存 1. 又称为一级缓存&#xff0c;mybatis自动开启。 2. 作用范围&#xff1a;同一…