MySQL的Redo Log跟Binlog

文章目录

    • 概要
    • Redo Log日志
      • Redo Log的作用
      • Redo Log的写入机制
    • Binlog日志
      • Binlog的作用
      • Binlog写入机制
    • 两段提交

概要

Redo Log和Binlog是MySQL日志系统中非常重要的两种机制,也有很多相似之处,本文主要介绍两者细节和区别。

Redo Log日志

Redo Log的作用

准备一张测试表

create table test_redo(id int primary key, c int);

假设现在要执行这样一条sql

update test_redo set c = c + 1 where id = 1;

修改一条数据,首先是修改了Buffer Pool中该条数据所在的数据页。假如说我们刚提交了事务,发生了某个故障,内存中的数据都失效了,就会导致所做的修改跟着丢失了。这是不能接受的。
如何避免这样的情况发生?
一个简单粗暴的做法是:在事务提交完成之前把该事务所修改的所有页面都刷新到磁盘
这样做有以下两个问题:

  1. 刷新一个完整的数据也太浪费
    比如上面只修改了一个字段,就要刷新整个页(16KB),InnoDB是以页为单位进行IO的,很浪费
  2. 随机IO速度很慢
    涉及到多个页时,页与页之间在磁盘上可能是不连续的,随机IO要比顺序IO慢很多。

为了达到系统崩溃后,服务重启也能恢复原来提交的事务修改的目的,同时避免出现上面提到的问题,Redo Log就是一种解决方案。

Redo Log,重做日志,其本质是记录⼀下事务对数据库做了哪些修改:

将第0号表空间的100号页面的偏移量为1处的值更新为2

具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 Redo Log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面。

这就是 MySQL 里经常说到的 WAL 技术,WAL 的全称是 Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。

通过事务执行过程中产生的redo日志刷新到磁盘的方式,跟前面提到的简单粗暴的方式比较,有如下好处:

  • redo日志占用的空间非常少
  • redo日志是顺序写入磁盘的

有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe

Redo Log的写入机制

日志文件
InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么总共就可以记录 4GB 的操作。从头开始写,写到末尾就又回到开头循环写,如下面这个图所示

在这里插入图片描述
write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

write pos 和 checkpoint 之间空着的部分,可以用来记录新的操作。如果 write pos 追上 checkpoint,表示写满,这时候不能再执行新的更新,把 checkpoint 推进一下。

可通过以下查询redo log文件的数量跟大小

show variables like '%innodb_log_file%';

在这里插入图片描述
在服务器端可看到对应的文件
在这里插入图片描述

redo log buffer

假如执行如下sql

begin;
insert into t1 ...
insert into t2 ...
commit;

这个事务要往两个表中插入记录,插入数据的过程中,还没有执行 commit 的时候,不能直接写到 redo log 文件里的。这时候会先记录在redo log buffer
redo log buffer 就是一块内存,用来先存 redo 日志。也就是说,在执行第一个 insert 的时候,数据的确发生了修改,redo log buffer 也写入了日志。但是,真正把日志写到 redo log 文件(文件名是 ib_logfile+ 数字),是在执行 commit 语句的时候做的

单独执行一个更新语句的时候,InnoDB 会自己启动一个事务,在语句执行完成的时候提交。过程跟上面是一样的。

redo log buffer是什么时候持久化到Redo Log中的呢?有如下3种策略,可通过innodb_flush_log_at_trx_commit进行配置。它有3种取值:

  1. 设置为 0 的时候,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中,由后台线程每隔1s执行一次刷盘操作 ;
  2. 设置为 1 的时候(默认值),表示每次事务提交时都将 redo log 直接持久化到磁盘;
  3. 设置为 2 的时候,表示每次事务提交时都只是把 redo log 写到 OS cache,然后由后台Master线程再每隔1秒执行OS
    cache -> flush cache to disk 的操作。

在这里插入图片描述

一般建议选择取值2,因为 MySQL 挂了数据没有损失,整个服务器挂了才会损失1秒的事务提交数据。设置为1时最为安全,但是性能也是最差。

Binlog日志

Binlog的作用

Redo Log 是属于InnoDB引擎所特有的日志,而MySQL Server层也有自己的日志,即 Binary log(二进制日志),简称Binlog。Binlog是记录所有数据库表结构变更以及表数据修改的二进制日志,不会记录SELECT和SHOW这类操作。Binlog日志是以事件形式记录,还包含语句所执行的消耗时间。

最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 能力,binlog 日志只能用于归档。而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统——也就是 redo log 来实现 crash-safe 能力。

Binlog日志有以下两个最重要的应用场景:

  1. 主从复制:在主库中开启Binlog功能,这样主库就可以把Binlog传递给从库,从库拿到Binlog后实现数据恢复达到主从数据一致性。
  2. 数据恢复:通过mysqlbinlog工具来恢复数据

Binlog日志文件记录模式有STATEMENT、ROW和MIXED三种,具体含义如下。

  • ROW(row-based replication, RBR):日志中会记录每一行数据被修改的情况,然后在slave端对相同的数据进行修改。
    优点:能清楚记录每一个行数据的修改细节,能完全实现主从数据同步和数据的恢复。
    缺点:批量操作,会产生大量的日志,尤其是alter table会让日志暴涨。

  • STATMENT(statement-based replication, SBR):每一条被修改数据的SQL都会记录到master的Binlog中,slave在复制的时候SQL进程会解析成和原来master端执行过的相同的SQL再次执行。简称SQL语句复制。
    优点:日志量小,减少磁盘IO,提升存储和恢复速度
    缺点:在某些情况下会导致主从数据不一致,比如last_insert_id()、now()等函数。

  • MIXED(mixed-based replication, MBR):以上两种模式的混合使用,一般会使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择写入模式。

可通过以下sql查看Binlog信息

show variables like '%log_bin%';
show variables like '%binlog%';

格式查看

mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.00 sec)

Biglog文件格式

MySQL的binlog文件中记录的是对数据库的各种修改操作,用来表示修改操作的数据结构是Log event。不同的修改操作对应的不同的log event。比较常用的log event有:Query event、Row event、Xid event等。binlog文件的内容就是各种Log event的集合。
Binlog文件中Log event结构如下图所示:

在这里插入图片描述

查看当前的二进制日志文件列表及大小。指令如下:

mysql> SHOW BINARY LOGS;
+---------------+-----------+-----------+
| Log_name      | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000004 |    712684 | No        |
| binlog.000005 |       179 | No        |
| binlog.000006 |       179 | No        |
| binlog.000007 |   3412930 | No        |
+---------------+-----------+-----------+
4 rows in set (0.00 sec)

查看具体的文件
语法:show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];

-- 文件内容太多了 这里限制了从 pos 156开始查看 限制5条
mysql> show binlog events in 'binlog.000004' from 156 limit 5 \G;
*************************** 1. row ***************************Log_name: binlog.000004Pos: 156Event_type: Anonymous_GtidServer_id: 1
End_log_pos: 235Info: SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
*************************** 2. row ***************************Log_name: binlog.000004Pos: 235Event_type: QueryServer_id: 1
End_log_pos: 317Info: BEGIN
*************************** 3. row ***************************Log_name: binlog.000004Pos: 317Event_type: Table_mapServer_id: 1
End_log_pos: 402Info: table_id: 92 (small_admin.QRTZ_CRON_TRIGGERS)
*************************** 4. row ***************************Log_name: binlog.000004Pos: 402Event_type: Delete_rowsServer_id: 1
End_log_pos: 502Info: table_id: 92 flags: STMT_END_F
*************************** 5. row ***************************Log_name: binlog.000004Pos: 502Event_type: XidServer_id: 1
End_log_pos: 533Info: COMMIT /* xid=392 */
5 rows in set (0.00 sec)

binlog是二进制文件,无法直接查看,借助mysqlbinlog命令工具了,可以查看其中的内容

# mysqlbinlog使用语法 
[root@node1 data]# mysqlbinlog --no-defaults --help

查看文件

mysqlbinlog --no-defaults --base64-output=decode-rows -vv binlog.000004 |tail -100

Binlog写入机制

事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 binlog 文件中。

一个事务的 binlog 是不能被拆开的,因此不论这个事务多大,也要确保一次性写入。这就涉及到了 binlog cache 的保存问题。

系统给 binlog cache 分配了一片内存,每个线程一个,参数 binlog_cache_size 用于控制单个线程内 binlog cache 所占内存的大小。如果超过了这个参数规定的大小,就要暂存到磁盘。

事务提交的时候,执行器把 binlog cache 里的完整事务写入到 binlog 中,并清空 binlog cache。

在这里插入图片描述

write 和 fsync 的时机,是由参数 sync_binlog 控制的:

  1. sync_binlog=0 的时候,表示每次提交事务都只 write,不 fsync;
  2. sync_binlog=1 的时候,表示每次提交事务都会执行 fsync;
  3. sync_binlog=N(N>1) 的时候,表示每次提交事务都 write,但累积 N 个事务后才 fsync。

因此,在出现 IO 瓶颈的场景里,将 sync_binlog 设置成一个比较大的值,可以提升性能。在实际的业务场景中,考虑到丢失日志量的可控性,一般不建议将这个参数设成 0,比较常见的是将其设置为 100~1000 中的某个数值。

但是,将 sync_binlog 设置为 N,对应的风险是:如果主机发生异常重启,会丢失最近 N 个事务的 binlog 日志。

两段提交

结合redo log 跟bin log ,执行update test_redo set c = c + 1 where id = 1 这条语句的大致过程如下:

  1. 执行器先找引擎取 id=1 这一行。id 是主键,引擎直接用树搜索找到这一行。如果 id=1 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
  2. 执行器拿到引擎给的行数据,把c的值加 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
  3. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
  4. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
  5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。

在这里插入图片描述

Q:为什么需要两段提交?

A:用上面的更新语句作为例子
如果不用两阶段提交,要么就是先写完 redo log 再写 binlog,或者是先写binlog再写redo log,下面对这两种情况讨论

  1. 先写 redo log 后写 binlog。假设在 redo log 写完,binlog 还没有写完时MySQL 进程异常重启。由于redo log 写完后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 c 的值是 1。 但是由于 binlog 没写完, binlog 里面就没有记录这条语句。因此,之后备份日志的时候用这个 binlog 来恢复临时库的话,就会与原库的值有差异。
  2. 先写 binlog 后写 redo log。如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,所以这一行 c 的值是 0。但是 binlog 里面已经记录了“把 c 从 0 改成 1”这个日志。在之后用 binlog 来恢复的时候就会与原库有差异。

Q:上图中,如果在时刻A,也就是写入 redo log 处于 prepare 阶段之后、写 binlog 之前,发生了奔溃呢?
A:由于此时 binlog 还没写,redo log 也还没提交,所以崩溃恢复的时候,这个事务会回滚。这时候,binlog 还没写,所以也不会传到备库

Q:如果在B时刻,也就是 binlog 写完,redo log 还没 commit 前发生 crash,那崩溃恢复的时候 MySQL 会怎么处理?
A:崩溃恢复时的判断如下

  1. 如果 redo log 里面的事务是完整的,也就是已经有了 commit 标识,则直接提交;
  2. 如果 redo log 里面的事务只有完整的 prepare,则判断对应的事务 binlog 是否存在并完整: a. 如果是,则提交事务; b. 否则,回滚事务。

Q:redo log 和 binlog 是怎么关联起来的?
A:它们有一个共同的数据字段,叫 XID。崩溃恢复的时候,会按顺序扫描 redo log:
如果碰到既有 prepare、又有 commit 的 redo log,就直接提交;
如果碰到只有 parepare、而没有 commit 的 redo log,就拿着 XID 去 binlog 找对应的事务。

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

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

相关文章

详解开源数据库审计平台Yearning

基本概念 数据库审计(简称DBAudit)能够实时记录网络上的数据库活动,对数据库操作进行细粒度审计的合规性管理,对数据库遭受到的风险行为进行告警,对攻击行为进行阻断。它通过对用户访问数据库行为的记录、分析和汇报&…

Unity EventSystem的一些理解和使用

Unity的EventSystem是用于处理用户输入和交互的系统。它是Unity UI系统的核心组件之一,可以用于捕捉和分发各种事件,例如点击、拖拽、按键、射线等。 常用的属性和方法有以下这些: 属性: current: 获取当前的EventSystem实例。…

Oracle-客户端连接报错ORA-12545问题

问题背景: 用户在客户端服务器通过sqlplus通过scan ip登陆访问数据库时,偶尔会出现连接报错ORA-12545: Connect failed because target host or object does not exist的情况。 问题分析: 首先,登陆到连接有问题的客户端数据库上,…

1. git入门操作

1. git入门操作 1、基本名词解释 图片 名词含义index索引区,暂存区master分支名,每个仓库都有个master,它作为主分支。branch其他分支,我们可以把master分支上的代码拷贝一份,重新命名为其他分支名work space就是我…

Rust语言入门教程(七) - 所有权系统

所有权系统是Rust敢于声称自己为一门内存安全语言的底气来源,也是让Rust成为一门与众不同的语言的所在之处。也正是因为这个特别的所有权系统,才使得编译器能够提前暴露代码中的错误,并给出我们必要且精准的错误提示。 所有权系统的三个规则…

C语言——从终端(键盘)将 5 个整数输入到数组 a 中,然后将 a 逆序复制到数组 b 中,并输出 b 中 各元素的值。

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int i;int a[5];int b[5];printf("输入5个整数&#xff1a;\n");for(i0;i<5;i){scanf("%d",&a[i]);}printf("数组b的元素值为&#xff1a;\n");for(i4;i>0;i--…

qt5.15.2及6.0以上版本安装

文章目录 下载在线安装器安装打开软件 下载在线安装器 因为从qt5.15开始不支持离线下载安装了&#xff0c;只能通过在线安装的方式进行安装。 下载在线安装下载器&#xff1a; 这个在线安装下载器网上也都是可以找到。 这里是其放到网盘上的下载地址&#xff1a; 链接&#x…

leetcode LCR24反转单链表

反转单链表 题目描述 题目分析 先来说迭代的思想&#xff1a; 上面next cur->next应该放在cur->next pre前面执行&#xff0c;这里笔误 再来说递归的思想&#xff1a; 题目代码 这个代码里面我加了我自己写的测试数据&#xff0c;自己可以去找对应的部分&#xff0c…

java springboot在测试类中构建虚拟MVC环境并发送请求

好 上文java springboot在测试类中启动一个web环境我们在测试类中搭了一个web环境 那么 下面就要想办法弄一个接口的测试 这边 我们还是要在controller包下去创建一个 controller类 写一个访问接口 这里 我创建一个 TestWeb.java 这里 我们编写代码如下 package com.example.…

【数据结构复习之路】树和二叉树(严蔚敏版)万字详解主打基础

专栏&#xff1a;数据结构复习之路 复习完上面四章【线性表】【栈和队列】【串】【数组和广义表】&#xff0c;我们接着复习 树和二叉树&#xff0c;这篇文章我写的非常详细且通俗易懂&#xff0c;看完保证会带给你不一样的收获。如果对你有帮助&#xff0c;看在我这么辛苦整理…

CCFCSP试题编号:202206-2试题名称:寻宝!大冒险!

一、题目 二、分析 因为藏宝图左下角位置一定是一棵树&#xff0c;所以只要把所有绿化图中每一棵树&#xff0c;与之相匹配&#xff0c;然后判断&#xff0c;是否整个藏宝图都是绿化图的一部分&#xff0c;如果是那就计数count1。所以来看&#xff0c;结果count最大也就是n(绿…

1、Docker概述与安装

相关资源网站&#xff1a; ● docker官网&#xff1a;http://www.docker.com ● Docker Hub仓库官网: https://hub.docker.com/ 注意&#xff0c;如果只是想看Docker的安装&#xff0c;可以直接往下拉跳转到Docker架构与安装章节下的Docker具体安装步骤&#xff0c;一步步带你安…

Mysql 8.0主从复制模式安装(兼容Mysql 5.7)

Mysql V8.0.35安装 官网地址&#xff1a;MySQL :: Download MySQL Community Server 下载【Mysql 8.0.35】压缩包 解压压缩包&#xff0c;仅保留6个安装文件即可 mysql-community-client-8.0.31-1.el7.x86_64.rpm mysql-community-client-plugins-8.0.31-1.el7.x86_64.rpm my…

摄影网站的技术 SEO:提示和最佳实践

摄影就是要给人留下良好的第一印象。如果你想在竞争中领先&#xff0c;摄影师的SEO是您可以采用的最佳营销方法之一。 我们都曾有过这样的经历&#xff1a;你建立了一个漂亮的作品集网站来吸引更多的业务。网站上线并在社交媒体上推广后&#xff0c;您就可以坐等了。网站访问量…

002、ArkTS

之——开发语言 目录 之——开发语言 杂谈 正文 1.TypeScript基础 1.1 基础类型 1.2 条件语句 1.3 函数 1.4 类 1.5 模块 1.6 迭代器 2.ArkTS 2.1 JAVA SCRIPT 2.2 TS 2.3 ArkTS ​编辑 3.示例 3.1 概述性示例 3.2 自定义组件 3.3 渲染控制语法 3.4 状态管…

linux升级gcc版本详细教程

0.前言 一般linux操作系统默认的gcc版本都比较低&#xff0c;例如centos7系统默认的gcc版本为4.8.5。gcc是从4.7版本开始支持C11的&#xff0c;4.8版本对C11新特性的编译支持还不够完善&#xff0c;因此如果需要更好的体验C11以及以上版本的新特性&#xff0c;需要升级gcc到一个…

P8A002-CIA安全模型-配置Linux描述网络安全CIA模型之可用性案例

【预备知识】 可用性&#xff08;Availability&#xff09; 数据可用性是一种以使用者为中心的设计概念&#xff0c;易用性设计的重点在于让产品的设计能够符合使用者的习惯与需求。以互联网网站的设计为例&#xff0c;希望让使用者在浏览的过程中不会产生压力或感到挫折&#…

F5社区学习心得分享:如何克服云迁移挑战?

伴随数字时代的快速发展&#xff0c;很多企业都会借助云迁移&#xff0c;踏上转型之旅。尽管云迁移被认为是一种能够节约成本&#xff0c;且不会影响正常运营的现代化改造举措&#xff0c;然而我们并不能低估它的复杂性。正如有研究表明&#xff0c;约有41%的企业并没有通过云迁…

JSP EL表达式之 empty

好 本文我们还是继续说EL表达式 我们来讲一个非空判断的好手 empty 我们直接编写代码如下 <% page contentType"text/html; charsetUTF-8" pageEncoding"UTF-8" %> <%request.setCharacterEncoding("UTF-8");%> <!DOCTYPE html&…

基于GPRS的汽车碰撞自动报警系统(论文+源码)

1. 系统设计 本次基于GPRS的汽车碰撞自动报警系统的设计中&#xff0c;其主要的目标功能如下&#xff1a;1、实时检测当前的GPS精度和纬度坐标&#xff1b;2.当发生碰撞后系统自动将当前的信息通过GPRS数据发送到远端数据进行报警&#xff1b;3、系统在碰撞后一方面进行本地报警…