MySQL三大日志(binlog、redo log和undo log)详解

news2024/11/23 10:07:42

MySQL三大日志binlog、redo log和undo log详解

  • 1.redo log
    • redo log概述
    • 刷盘时机
      • innodb_flush_log_at_trx_commit=0
      • innodb_flush_log_at_trx_commit=1
      • innodb_flush_log_at_trx_commit=2
    • 日志文件组
  • 2.binlog
    • binlog 概述
    • 记录格式
    • 写入机制
    • 刷盘时机
  • 3.两阶段提交
  • 4.undo log
  • 5.总结

1.redo 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 文件里。

刷盘时机

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

  • 0 :设置为 0 的时候,表示每次事务提交时不进行刷盘操作
  • 1 :设置为 1 的时候,表示每次事务提交时都将进行刷盘操作 (默认值)
  • 2 :设置为 2 的时候,表示每次事务提交时都只把 redo log buffer 内容写入 page cache

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

也就是说,一个没有提交事务的 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日志文件大小都是一样的。

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


2.binlog

binlog 概述

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

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

不管用什么存储引擎,只要发生了表数据更新,都会产生 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,这样可以为数据库的恢复与同步带来更好的可靠性。

但是这种格式,需要更大的容量来记录,比较占用空间,恢复与同步时会更消耗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里面的 binlog 会丢失。

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

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

在出现IO瓶颈的场景里,将sync_binlog设置成一个比较大的值,可以提升性能。同样的,如果机器宕机,会丢失最近N个事务的binlog日志。🫠


3.两阶段提交

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认为是完整的,就会提交事务恢复数据。


4.undo log

我们知道如果想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行回滚,在 MySQL 中,恢复机制是通过 回滚日志(undo log) 实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,我们直接利用 回滚日志 中的信息将数据回滚到修改之前的样子即可!并且,回滚日志会先于数据持久化到磁盘上。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务。

另外,MVCC 的实现依赖于:隐藏字段、Read View、undo log。在内部实现中,InnoDB 通过数据行的 DB_TRX_IDRead View 来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR 找到 undo log 中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 Read View 之前已经提交的修改和该事务本身做的修改


5.总结

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

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

本教程基于JavaGuide - 数据库篇 - 三大日志详解

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

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

相关文章

SSL和TLS协议如何提供身份验证、机密性和完整性

SSL 和 TLS 协议使两方能够相互识别和验证,并以机密性和数据完整性进行通信。SSL 和 TLS 协议通过 Internet 提供通信安全性,并允许客户端/服务器应用程序以保密和可靠的方式进行通信。这些协议有两层:记录协议和握手协议,它们位于…

要命!我篡改了系统命令惊现事故,竟要扣我年终奖-Golang-cobra

打工还是要打工的。。我最后也没发出去。 紧急处理以后,现在写复盘,大家随我看看我到底是在学习哪些内容。 (以上内容纯属虚构,如有雷同纯属巧合) 简介 之前我们讲过pflag和os.Args,现在说说cobra这个命令行…

如何将SQL Server数据从表导出到CSV文件

在本文中,我们将使用四种不同的工具将表从SQL Server导出到.csv文件。此外,你将学习如何将带有或不带有头的SQL查询结果导出到.csv文件。 SQL Server数据从表导出到CSV文件 使用SQL Server Management Studio将SQL结果导出到具有或不具有标题的CSV文件一、不带标题二、带标题…

图形编辑器:图形和辅助线绘制的坐标问题

大家好,我是前端西瓜哥。今天看看绘制图形和辅助线时,坐标转换的一些注意点。 项目地址,欢迎 star: https://github.com/F-star/suika 线上体验: https://blog.fstars.wang/app/suika/ 先回顾一下之前讲的视口坐标和场…

docker镜像与容器实践

一、引子 镜像和容器是不同的概念,本文主要是为了通过实践来强化对这两种不同概念的理解。 二、安装docker 安装docker,执行以下命令即可: # 安装依赖 yum install -y yum-utils device-mapper-persistent-data lvm2 # 设置国内源 yum-co…

显示Linux系统上的服务

init 和 systemd 都是 Linux的 init 守护进程,systemd出现较晚,最近的 Linux 发行版中很常用。init 使用service命令管理服务,而Systemd用systemctl命令管理服务。init 和 systemd 都是 Linux的 init 守护进程,即使你的 Linux 系统…

Maven3.8.*系列 settings.xml详解

文章目录文末,拿完整Settings配置文件设置参考介绍简要概述设置详细信息简单的价值观插件组服务器密码加密的镜像代理配置文件激活性能库插件的储存库活动概况直达文末,拿完整Settings配置文件结语文末,拿完整Settings配置文件 设置参考 介绍 简要概述 的 settings 元素 set…

返乡上云图

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

PicGo+Github搭建图床

文章目录一、Github仓库创建二、配置PicGo三、实际体验四、PicGo 2.3.1参考资料一、Github仓库创建 PS:它只会显示一次,所以最好把它复制下来到你的备忘录存好,方便下次使用,否则下次有需要重新新建; 二、配置PicGo …

Linux进程控制(进程退出+进程等待)

目录 一、子进程创建 1.1 fork函数深入 1.2 写时拷贝 二、进程退出 2.1.1 进程退出码概念 2.1.2 系统退出码文字描述 2.1.3 _exit和exit函数 2.1.4 查看退出码 三、进程等待 3.1 进程等待解决僵尸进程 3.2 进程等待方法 3.2.1 wait 3.2.2 waitpid() 四、…

seata部署指南(v1.6.1)

Seata 搭建 db模式版本 V1.6.1一、 简介二、下载三、建表(仅db)四、配置 seata server 参数4.1、V1.4.2之前方式4.2、V1.4.2 之后推荐方式(seataServer.properties)五、配置Server5.1、 修改 appplication.yml5.1.1、 修改 appplication.yml seata.store…

文件操作(File类)

文章目录一、初识文件二、File类构造方法常用方法一、初识文件 我们目前是如何存储数据的?弊端是什么? int a 1; int[] arr new int[5];我们这些数据是在内存中存储的,是不能够长久保存的。 那么,我们的计算机当中有没有一块硬件可以长久存储数据…

PostgreSQL(一)Windows安装

目录一、下载二、安装PostgreSQL三、安装StackBuilder四、打开PostgreSQL管理工具pgAdmin五、打开命令行一、下载 下载地址: https://www.enterprisedb.com/downloads/postgres-postgresql-downloads 下载后安装包如下: 二、安装PostgreSQL 双击打开安…

DataX使用入门

DataX 是阿里云 DataWorks数据集成 的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS 等各种异构数据…

Java 日志框架 Log4J

文章目录引言什么是Log4JLog4J三大组件Log4J日志级别Log4J基本使用自定义配置文件Appender示例FileAppenderDailyRollingFileAppenderRollingFileAppenderJDBCAppender自定义Logger引言 Java 日志框架 JUL 在这篇文章中已经向大家介绍了我们为什么要使用日志文件、常见的日志…

张力调节(精密调节气阀应用)

跳舞轮对应张力调节范围,我们可以通过改变气缸的气压方式间接改变,张力跳舞轮在收放卷闭环控制上的详细应用,可以参看下面的文章链接,这里我们主要讨论精密可调气阀的模拟量编程问题。 PLC张力控制(开环闭环算法分析&…

【实践向】当移除了三级缓存……

本文会手把手带你一起把使用二级缓存替换三级缓存,看下移除了三级缓存,只有二级缓存会出什么问题,用实践回答那个被问了无数次的“为什么要有三级缓存?”以及“二级缓存解决不了循环依赖问题吗?”等类似问题(&#xff…

“Flash配置不当漏洞”详解

危害 可被用来进行跨域访问,可能会导致“跨站点伪造请求”或“跨站点跟踪”(“跨站点脚本编制”的变体)之类的攻击,从而导致其它用户的信息被非法读取。 导致不受信任的第三方域的flash也能访问当前域的资源,绕过同源策…

一、构建自己的图像分类数据集(Datawhale组队学习)

文章目录安装配置环境图像采集采集函数爬取一类图片爬取多类图片一些参考类别的关键词制作图像分类数据集的注意事项删除多余文件删除系统自动生成的多余文件删除gif格式的图像文件删除非三通道的图像统计图像尺寸、比例分布采用的数据集统计数据集的基本信息可视化图像尺寸分布…

Embarcadero Dev-C++第一次使用注意事项

Embarcadero Dev-C第一次使用注意事项 Embarcadero Dev-C简介 2000年左右,Bloodshed software开发了Dev-C ,提供轻量、免费、开源的C/CIDE。Dev-C是最适合初学C语言的IDE之一,但至2015年Dev C5.11,停止了更新维护了。 后来&…