mysql 两种重要的日志

news/2025/3/17 17:45:18/文章来源:https://www.cnblogs.com/aoximin/p/18342183

前言

这个不用多说,两种重要的日志分别是redo log 和 binlog,这两种,下面分别来结束。

正文

先来redo log, redo log 是inno db 引擎特有的,运用了一种wal 技术,全称是: write-ahead logging.

它的关键点就是先写日志,再写磁盘,也就是先写粉板,等不忙的时候再写账本。

简单来说就是先写内存,然后写redo log,这样就结束了,而不需要立马写入到磁盘中去,避免了频繁的io操作开销,这里面的优点就不言而喻了。

那么redo log 是怎么样的呢?

redo log 一共4个文件,如上文所述,每个文件大小是1个g。

上图中有两个字段,分别是write pos(write position) 和 check point,

那么redo log 也不可能一直不将数据写入到磁盘中对吧。

那么write pos一直向前,check point就再后面一直更新数据库,这样就形成了一个环。

当write pos 追赶到check point的时候那么这个时候怎么办呢? 这个时候redo log就只能不让提交了,不让提交的话,那么这个时候就所有的操作都进入了等待状态了。

需要等待check point 和 write pos 距离拉开后,然后数据库才能继续操作。

这样即使重启,那么也不会有啥问题,因为反正redo log已经写了,只要把redo log 更新即可。

redo log,全称是ready do log,就是正要准备去做的日志。

前面提及到redo log 是inno db的日志,那么service 层有没有日志,也有叫做bin log,全称binary log,用于归档使用的。

这两种日志有以下三点不同。

  1. redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。

  2. redo log是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的
    是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。

针对第二点进行解释一下:

1. Redo log:- Redo log 是用于数据库的事务日志,记录了数据库中发生的每个数据修改操作,包括数据更改前和更改后的内容。这样可以通过重做日志回滚未提交的事务或者恢复系统崩溃后的数据一致性。- Redo log 是在事务执行过程中生成并写入磁盘的,在数据库引擎中起到数据保护和恢复的作用。2. Binlog(二进制日志):- Binlog 记录了数据库执行的所有语句,可以是创建表、更新数据或者删除数据的操作,并未记录每个数据修改的具体内容。- Binlog 的内容是与数据库服务器的操作相关联的 SQL 语句,可以用于灾难恢复、备份、数据库复制等操作,不同服务器之间可以通过 Binlog 来保持数据的同步。总的来说,Redo log 记录的是数据修改的物理操作记录,而 Binlog 记录的是逻辑操作的 SQL 语句记录。两者虽然存在共同点,但在数据恢复和保护上有着不同的功能和作用。
假设有一个数据库表,其中有一行数据的内容为 "John Doe",现在执行了一个更新操作,将该行数据修改为 "Jane Smith"。这个更新操作会生成一个 Redo log 记录,其中包含了修改前的数据 "John Doe" 和修改后的数据 "Jane Smith",以及相关的事务信息。这样,如果系统发生故障或者需要回滚操作,数据库可以通过 Redo log 中的记录来恢复数据到更新之前的状态。

在MySQL中,Redo日志会记录主键索引和聚簇索引页的修改,但不会记录二级索引页的修改。 Redo日志会记录对数据页的修改,而二级索引页属于辅助索引,不包含在Redo日志中。

然后change buffer 只是针对二级索引的更新有效,对主键索引这种一级索引是无效的,这个需要理解,redo 日志会记录数据更新前的数据和数据更新后的数据。

  1. redo log是循环写的,空间固定会用完;binlog是可以追加写入的。“追加写”是指binlog文件
    写到一定大小后会切换到下一个,并不会覆盖以前的日志。

有了对这两个日志的概念性理解,我们再来看执行器和InnoDB引擎在执行这个简单的update语
句时的内部流程。

  1. 执行器先找引擎取ID=2这一行。ID是主键,引擎直接用树搜索找到这一行。如果ID=2这一
    行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然
    后再返回。

  2. 执行器拿到引擎给的行数据,把这个值加上1,比如原来是N,现在就是N+1,得到新的一行
    数据,再调用引擎接口写入这行新数据。

  3. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处
    于prepare状态。然后告知执行器执行完成了,随时可以提交事务。

  4. 执行器生成这个操作的binlog,并把binlog写入磁盘。

  5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交(commit)状态,更
    新完成

将redo log的写入拆成了两个步骤:prepare和commit,这就是"两阶段提交"。

为什么必须有“两阶段提交”呢?这是为了让两份日志之间的逻辑一致。要说明这个问题,我们得
从文章开头的那个问题说起:怎样让数据库恢复到半个月内任意一秒的状态? 怎
前面我们说过了,binlog会记录所有的逻辑操作,并且是采用“追加写”的形式。如果你的DBA承
诺说半个月内可以恢复,那么备份系统中一定会保存最近半个月的所有binlog,同时系统会定期
做整库备份。这里的“定期”取决于系统的重要性,可以是一天一备,也可以是一周一备。

当需要恢复到指定的某一秒时,比如某天下午两点发现中午十二点有一次误删表,需要找回数
据,那你可以这么做:

首先,找到最近的一次全量备份,如果你运气好,可能就是昨天晚上的一个备份,从这个备
份恢复到临时库;

然后,从备份的时间点开始,将备份的binlog依次取出来,重放到中午误删表之前的那个时
刻。

  1. 先写先 redo log r 后写后 binlog b 。假设在redo log写完,binlog还没有写完的时候,MySQL进程异
    常重启。由于我们前面说过的,redo log写完之后,系统即使崩溃,仍然能够把数据恢复回
    来,所以恢复后这一行c的值是1。
    但是由于binlog没写完就crash了,这时候binlog里面就没有记录这个语句。因此,之后备份
    日志的时候,存起来的binlog里面就没有这条语句。
    然后你会发现,如果需要用这个binlog来恢复临时库的话,由于这个语句的binlog丢失,这
    个临时库就会少了这一次更新,恢复出来的这一行c的值就是0,与原库的值不同。
  2. 先写先 binlog b 后写后 redo log r 。如果在binlog写完之后crash,由于redo log还没写,崩溃恢复以
    后这个事务无效,所以这一行c的值是0。但是binlog里面已经记录了“把c从0改成1”这个日
    志。所以,在之后用binlog来恢复的时候就多了一个事务出来,恢复出来的这一行c的值就是
    1,与原库的值不同。

你可能会说,这个概率是不是很低,平时也没有什么动不动就需要恢复临时库的场景呀?
其实不是的,不只是误操作后需要用这个过程来恢复数据。当你需要扩容的时候,也就是需要再
多搭建一些备库来增加系统的读能力的时候,现在常见的做法也是用全量备份加上应用binlog来
实现的,这个“不一致”就会导致你的线上出现主从数据库不一致的情况。
简单说,redo log和binlog都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保
持逻辑上的一致。

redo log用于保证crash-safe能力。innodb_flush_log_at_trx_commit这个参数设置成1的时候,
表示每次事务的redo log都直接持久化到磁盘。这个参数我建议你设置成1,这样可以保证
MySQL异常重启之后数据不丢失。
sync_binlog这个参数设置成1的时候,表示每次事务的binlog都持久化到磁盘。这个参数我也建
议你设置成1,这样可以保证MySQL异常重启之后binlog不丢失。

redo log 和 binlog是怎么关联起来的?

回答:它们有一个共同的数据字段,叫XID。崩溃恢复的时候,会按顺序扫描redo log:

如果碰到既有prepare、又有commit的redo log,就直接提交;

如果碰到只有parepare、而没有commit的redo log,就拿着XID去binlog找对应的事务。

处于 : prepare阶段的 阶 redo log加上完整 加 binlog,重启就能恢
复,而不是将redo log删除呢,MySQL为什么要这么设计?

在时刻B,也就是binlog写完以后MySQL发生崩溃,这时候binlog已经写入了,之后就会被从库(或者用这个binlog恢复出来的库)使用。

如果这样的话,为什么还要两阶段提交呢?干脆先 : redo log写完,再写 写
binlog。崩溃恢复的时候,必须得两个日志都完整才可以。是不是一样的逻辑?

对于InnoDB引擎来说,如果redo log提交完成了,事务就不能回滚(如果这还允许回滚,就可能
覆盖掉别的事务的更新)。而如果redo log直接提交,然后binlog写入的时候失败,InnoDB又回
滚不了,数据和binlog日志又不一致了。

正常运行中的实例,数据写入后的最终落盘,是从 : redo log更新过来的 更
还是从 还 buffer pool更新过来的呢?

实际上,redo log并没有记录数据页的完整数据,所以它并没有能力自己去更新磁盘数据页,也
就不存在“数据最终落盘,是由redo log更新过去”的情况。

  1. 如果是正常运行的实例的话,数据页被修改以后,跟磁盘的数据页不一致,称为脏页。最终
    数据落盘,就是把内存中的数据页写盘。这个过程,甚至与redo log毫无关系。

  2. 在崩溃恢复场景中,InnoDB如果判断到一个数据页可能在崩溃恢复的时候丢失了更新,就
    会将它读到内存,然后让redo log更新内存内容。更新完成后,内存页变成脏页,就回到了
    第一种情况的状态。

下一结介绍一下为什么很多公司选择读可提交作为模式。

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

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

相关文章

STM32H7 HAL库CubeMX 双重ADC模式同步采样详细配置+FFT计算相位差

前言 在电赛备赛期间琢磨了一下ADC同步采样的实现方式,本来是打算直接用AD7606来着,但是搞了半天也没把驱动整出来...考虑到AD7606本身采样率也拉不到太高,于是就花了几天时间把片上ADC配出来了。查资料的时候我发现关于STM32双重ADC模式的资料是真的少,用FFT算两路信号相位…

Python pymodbus类库使用学习总结

实践环境 Python 3.9.13 https://www.python.org/ftp/python/3.9.13/python-3.9.13-amd64.exe pymodbus-3.6.8-py3-none-any.whl https://files.pythonhosted.org/packages/35/19/a9d16f74548d6750acf6604fa74c2cd165b5bc955fe021bf5e1fa04acf14/pymodbus-3.6.8-py3-none-any.w…

ThinkAdmin_v6两个简单漏洞(文件读取+信息泄露)

危险函数:file_get_contents()第二次遇到侵权声明 本文章中的所有内容(包括但不限于文字、图像和其他媒体)仅供教育和参考目的。如果在本文章中使用了任何受版权保护的材料,我们满怀敬意地承认该内容的版权归原作者所有。 如果您是版权持有人,并且认为您的作品被侵犯,请通…

ubuntu22.04容器安装ssh服务

除了特别说明外,否则以下命令均为ubuntu 22.04 容器内执行!!!安装 查看ubuntu22.04 有没有安装openssh-server,执行命令:sudo dpkg --list | grep ssh没有找到openssh-server的包,很显然,没有安装,那么就开始安装,执行:sudo apt install openssh-server安装完成后,…

3.Java基础语法

注释单行注释 //单行注释 //输入一个Hello World!多行注释:可以注释一段文字 /* 注释 */ //多行注释:可以注释一段文字 /* 注释 */ /* 多行注释 多行注释 多行注释 */文档注释:JavaDoc /** * @Description HelloWorld * @Author 爱吃麻辣烫的妹纸 */⭐️注意:书写注释是…

分享圣诞树+雪人+全屏动效

分享圣诞树+雪人+全屏动效 创建时间:2024年8月4号 分享之前学习老师发的几个小玩意 一、圣诞树 运行: 点击该exe即可出来一棵圣诞树。退出: 鼠标点击该圣诞树右键二、雪人 运行: 双击点开exe即可退出: 和圣诞树一样、 三、音乐:满满都是爱 运行:双击打开,该程序对鼠标的…

java:一键生成二维码工具类

前言:本工具选择了Zxing,他是一个开源的,使用java实现多种格式的1D/2D条码图像处理库, 1.pom添加依赖<!-- 二维码生成&识别组件 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>…

Luogu P10842 Piggy and Trees 题解 [ 绿 ] [ 拆边 ] [ 贡献思维 ]

Piggy and Trees:把路径拆成边的思维题。 思路 一看到这题的路径,就想到了 Luogu P3177 树上染色 这题化路径为边的贡献,分别计算的思维。 那么对于此题,先来观察题目里式子的意思:对于树上的每个无序点对,求出树上每个点 到这些点对之间的最短路径的 距离之和。枚举点对…

ZeRO:一种去除冗余的数据并行方案

ZeRO:一种去除冗余的数据并行方案 目前训练超大规模语言模型主要有两条技术路线:TPU + XLA + TensorFlow/JAX GPU + Pytorch + Megatron + DeepSpeed 前者由Google主导,由于TPU和自家云平台GCP深度绑定,对于非Googler来说并不友好 后者背后则有NVIDIA、Meta、MS等大厂加持,…

【攻防技术系列+权限维持】注册表运行键

在红队行动期间在网络中获得初步立足点是一项耗时的任务。因此,持久化是红队行动成功的关键,因为这将使团队能够专注于交战目标,而不会失去与指挥和控制服务器的通信。 创建将在 Windows 登录期间执行任意负载的注册表项是红队剧本中最古老的隐藏技巧之一。这种持久性技术需…

链表part02

今天是8月3日,学习了链表的第二部分。交换链表两个节点,考察对next的操作和tmp的灵活运用。 删除链表的倒数第N个节点,双指针减少遍历次数。 链表相交,移动链表尾对齐,其实就是动长链表的指针。 环形链表,记住方法。4. 24交换链表两个节点 题目:给你一个链表,两两交换其…

Qt-pyqt6与QTDesginers的相互使用技巧

1. 先在QT Designers Tools 设计器中画好框架,再保存为.ui文件导出 2. 再pycharm中创建一个main.py文件用来加载和使用这个.ui文件,通用的代码如下: main.py from PyQt6.QtGui import QIntValidator, QIcon from PyQt6.QtWidgets import QApplication, QLabel, QListWidgetI…