MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log

news2025/1/27 16:55:29

文章目录

  • 一、前言
    • 1.1 MySQL体系结构
    • 1.2 MySQL日志分类
    • 1.3 其他几种日志
      • 1.3.1 查询日志
      • 1.3.2 慢查询日志
      • 1.3.3 错误日志
  • 二、bin log 二进制日志
    • 2.1 bin log简介
    • 2.2 binlog日志格式
    • 2.3 日志删除
    • 2.4 写入/刷盘机制
  • 三、undo log 回滚日志
    • 3.1 undo log简介
    • 3.2 隐藏字段 —— 事务ID(TRX_ID)、ROLL_PTR
    • 3.3 版本链
  • 四、redo log 重做日志
    • 4.1 redo log详解
    • 4.2 redo log的写入过程、刷盘时机
    • 4.3 redo log file 的结构
    • 4.4 什么是 crash-save
    • 4.5 redo log细节
  • 五、补充
    • 5.1 binlog与redolog对比、逻辑日志与物理日志
    • 5.2 update语句的执行流程
    • 5.3 两阶段提交
    • 5.4 总结、使用场景
      • binlog的应用场景
      • undolog的使用场景
      • redolog的使用场景

MySQL作为最流行的开源数据库,其重要性不言而喻。日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息。常见的日志有以下几种:
在这里插入图片描述

作为开发,我们重点需要关注的是 二进制日志bin log(归档日志)事务日志redo log(重做日志)undolog(回滚日志),本文接下来会详细介绍这三种日志。

  • 二进制binlog(归档日志):是Server层生成的日志,主要用于数据备份和主从复制;
  • undolog(回滚日志):是Innodb存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和MVCC
  • 事务日志redolog(重做日志):是Innodb存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复

下面就带着这个问题,看看这三种日志是怎么工作的。

一、前言

1.1 MySQL体系结构

在这里插入图片描述
在这里插入图片描述

1)连接层

最上层是一些客户端和链接服务,包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。

2)服务层

第二层架构主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如过程、函数等。在该层,服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定表的查询的顺序,是否利用索引等,最后生成相应的执行操作。如果是select语句,服务器还会查询内部的缓存,如果缓存空间足够大,这样在解决大量读操作的环境中能够很好的提升系统的性能。

3)引擎层

存储引擎层,存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。数据库中的索引是在存储引擎层实现的。

4)存储层

数据存储层,主要是将数据(如: redolog、undolog、数据、索引、二进制日志、错误日志、查询日志、慢查询日志等)存储在文件系统之上,并完成与存储引擎的交互。

和其他数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎上,插件式的存储引擎架构,将查询处理和其他的系统任务以及数据的存储提取分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。

其中slowlog、binlog、errorlog、relaylog归属于MySQL服务层;undolog、redolog归属于引擎层,为innodb所特有。

1.2 MySQL日志分类

MySQL有不同类型的日志:慢查询日志、通用查询日志、错误日志、事务日志、二进制日志等几大类,在MySQL8之后又新增了两种日志——中继日志、数据定义语句日志。其中比较重要的是二进制日志binlog (归档日志) 、事务日志redo log(重做日志) 和 undo log(回滚日志)。

MySQL日志主要包括八种

  • 慢查询日志(slow query log):记录所有执行时间超过long_query_time的所有查询,方便对查询进行优化
  • 通用查询日志(general log):记录索引连接的起始时间和终止时间,以及连接发送给数据库服务的所有指令,对复原操作的实际场景、发现问题、数据库操作的审计都有帮助
  • 二进制日志(bin log):记录所有更改数据的语句,用于主从服务器之间的数据同步、服务器遇到故障时数据的无损恢复
  • 错误日志(error log):记录MySQL服务的启动、运行或停止MySQL服务时出现的问题,方便了解服务器的状态,从而对服务器进行维护
  • 中继日志(relay log):用于主从服务器架构,从服务器用来存放主服务器二进制日志内容的一个中间件文件。从服务器通过读取中继日志的内容,来同步主服务器上的操作
  • 回滚日志(undo log):是Innodb存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和MVCC
  • 重做日志(redo log):是Innodb存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复
  • 数据定义语句日志:记录数据定义语句执行的元数据操作

除了二进制日志外,其他日志均为文本文件。默认情况下,所有日志均创建于MySQL数据目录中

1.3 其他几种日志

1.3.1 查询日志

查询日志中记录了客户端的所有操作语句(包括所有的增删改查、DDL、DML、DQL语句),而二进制日志不包含查询数据的SQL语句。默认情况下,查询日志是未开启的。如果需要开启查询日志,可以设置以下配置:
在这里插入图片描述
在这里插入图片描述

如果想要禁用查询日志,可将general_log设置为0,而后重启MySQL服务sudo systemctl restart mysql

1.3.2 慢查询日志

慢查询日志记录了所有执行时间超过参数 long_query_time 设置值并且扫描记录数不小于 min_examined_row_limit 的所有SQL语句的日志,默认未开启。long_query_time 默认为10秒,最小为0,精度可以到微秒。如果要开启慢查询日志,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:

# 开启MySQL慢日志查询开关
slow_query_log=1
# 执行时间参数,设置慢日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志
long_query_time=2

在这里插入图片描述
在这里插入图片描述

同理,如果想要禁用慢查询日志,可将slow_query_log设置为0,而后重启MySQL服务sudo systemctl restart mysql

1.3.3 错误日志

错误日志是MySQL中最重要的日志之一,它记录了当mysqld启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时,建议首先查看此日志。

该日志是默认开启的,默认存放目录/var/log/,默认的日志文件名为mysqld.log。查看日志位置:

-- 登录mysql,查看系统变量
show variables like '%log_error';

在这里插入图片描述

二、bin log 二进制日志

2.1 bin log简介

二进制日志(BINLOG)记录了所有的DDL(数据定义语言,创建库、表)语句和DML数据操纵语言,增删改)语句,但不包括数据查询(SELECT、SHOW)语句

作用:1.灾难时的数据恢复;2.MySQL的主从复制

  • binlog用于记录数据库执行的DDL、DML操作信息(不包括查询),以二进制的形式保存在磁盘中。binlog是mysql的逻辑日志,并且由Server层进行记录,使用任何存储引擎的mysql数据库都会记录binlog日志。
  • binlog是通过追加的方式进行写入的,可以通过max_binlog_size参数设置每个binlog文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。

在MySQL8版本中,默认二进制日志是开启着的,涉及到的参数如下:

show variables like '%log_bin';

在这里插入图片描述

常用的5.7版本可能只有以下参数:

mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.35    |
+-----------+
1 row in set (0.00 sec)

mysql> show variables like '%log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | OFF   |
| sql_log_bin   | ON    |
+---------------+-------+
2 rows in set (0.00 sec)

2.2 binlog日志格式

binlog日志有三种格式:分别为STATMENT、ROW和MIXED,具体格式及特点如下:

  • STATMENT:基于SQL语句的复制,每一条会修改数据的sql语句会记录到binlog中。
    • 优点:不需要记录每一行的变化,减少了binlog日志量,节约了IO,从而提高了性能;
    • 缺点:在某些情况下会导致主从数据不一致,比如执行sysdate()、sleep()等。
  • ROW:基于行的复制,不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了。
    • 优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题;
    • 缺点:会产生大量的日志,尤其是alter table的时候会让日志暴涨
  • MIXED:基于 STATMENT 和 ROW 两种模式的混合复制,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog
日志格式含义
STATEMENT基于SQL语句的日志记录,记录的是SQL语句,对数据进行修改的SQL都会记录在日志文件中
ROW默认格式,基于行的日志记录,记录是每一行的数据变更
MIXED混合了STATEMENT和ROW两种格式,默认采用STATEMENT,在某些特殊情况下会自动切换为ROW进行记录
show variables like '%binlog_format%';

-- 如果想修改二进制日志格式
--  1.vim /etc/my.cnf
--  2.往文件内添加 binlog_format=STATEMENT
--  3.systemctl restart mysqld

在这里插入图片描述

具体日志格式详解

由于日志是以二进制方式存储的,不能直接读取,需要通过二进制日志查询工具mysqlbinlog来查看,具体语法:

mysqlbinlog [options] log-files

参数选项:
    -d, --database=name     指定数据库名称,只列出指定的数据库相关操作
    -o, --offset=#          忽略掉日志中的前n行命令
    -v, --verbose           将行事件(数据变更)重构为SQL语句
    -vv                     将行事件(数据变更)重构为SQL语句,并输出注释信息
    
    
mysqlbinlog -v binlog.00002

mysql中有score记录成绩,执行 update score set math = math + 1;

ROW格式下,执行mysqlbinlog -v binlog.00002,得到如下内容

在这里插入图片描述

STATEMENT格式下,执行mysqlbinlog binlog.00003,得到如下内容

在这里插入图片描述

2.3 日志删除

对于比较繁忙的业务系统,每天生成的binlog数据巨大,如果长时间不清除,将会占用大量磁盘空间。可以通过以下几种方式清理日志:

MySQL指令含义
reset master;删除全部binlog日志,删除之后,日志编号将从binlog.000001重新开始
purge master logs to ‘binlog.******’;删除******编号之前的所有日志
purge master logs before ‘yyyy-mm-dd hh24:mi:ss’;删除日志为“yyyy-mm-ddhh24:mi:ss"之前产生的所有日志

2.4 写入/刷盘机制

事务执行过程中,先把日志写入binlog cache,事务提交时,再把binlog cache写到binlog文件中。一个事务的binlog不能被拆开,确保一次性写入,系统将给每个线程分配一块内存作为binlog cache

对于InnoDB存储引擎而言,只有在事务提交时才会记录binlog,那么binlog什么时候才会将内存中的数据刷到磁盘呢?其实mysql是通过sync_binlog参数控制binlog的刷盘时机,取值范围是0-N【write和fsync的时机,由参数sync_binlog控制,默认为0】

  • 0:每次提交事务都只write,由系统自行判断什么时候执行fsync。虽然性能得到提升,但是机器宕机,page cache里的binlog会丢失(不去强制要求,由系统自行判断何时写入磁盘)
  • 1:每次提交事务都会执行fsync,如同redolog刷盘流程一样(每次commit的时候都要将binlog写入磁盘)
  • N:每次提交事务都write,但累计N个事务后才fsync(每N个事务,才会将binlog写入磁盘)

在出现IO瓶颈时,将sync_binlog设置成一个较大的值,能提升性能。同样的,若机器宕机会丢失最近N个事务的binlog日志

三、undo log 回滚日志

3.1 undo log简介

undo log(回滚日志):是Innodb存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和MVCC

它是InnoDB存储引擎在insert、update、delete的时候产生的便于数据回滚的日志。在数据更新之前,MySQL就需要先把更新前的数据记录到 undo log 日志中,当事务回滚时,可以利用 undo log 来进行回滚。作用包含两个——提供回滚、MVCC(多版本并发控制)。undo log主要分为两种:

  • insert undo log:当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除(因为这种log只是对本事务可见,其他事务不可见,所以当事务提交后,这种类型的undo log就会被系统直接删除回收,也就是该undo log占用的undo页面链表被释放)。
  • update undo log:update、delete的时候,产生的undo log日志不仅在事务回滚时需要,在快照读时也需要(也就是MVCC),所以不能在事务提交后马上删除,只在提交后放入undo log的链表,等待purge线程进行最后的删除。

事务需要保证原子性,也是说事务中的操作要么全部完成,要么什么也不做。如果事务执行到一半,出错了怎么办-回滚。但是怎么回滚呢,靠 undo 日志。undo 日志就是我们执行sql的逆操作

  • undo 日志有两个作用:提供回滚和多个行版本控制(MVCC)
  • 数据页里一行数据的格式 见3.3版本链,其中 roll_point 会指向一个undo 日志
  • undo 日志一般会在事务提交时被删除,但是如果 undo 日志为 MVCC 服务 则暂时保留
  • 一个事务会产生多个 undo 日志,mysql有专门的 undo 页 保存 undo 日志。innodb 会为每一个事务单独分配 undo 页链表(最多分配 4 个链表)

比如现在Tom的账户余额有100,现在有一个事务需要把Tom的账户余额更新为300,大致的流程如下图:

在这里插入图片描述

3.2 隐藏字段 —— 事务ID(TRX_ID)、ROLL_PTR

在这里插入图片描述

当我们创建了上面的这张表,我们在查看表结构的时候,就可以显式的看到 id、user_name、balance、wealth 这四个字段。 实际上除了这四个字段以外,InnoDB还会自动的给我们添加三个隐藏字段,分别是:

隐藏字段含义
DB_TRX_ID最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。
DB_ROLL_PTR回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。
DB_ROW_ID隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。

而上述的前两个字段是肯定会添加的, 是否添加最后一个字段DB_ROW_ID,得看当前表有没有主键,如果有主键,则不会添加该隐藏字段。

3.3 版本链

不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。

在这里插入图片描述

然后,有四个并发事务同时在访问这张表。

在这里插入图片描述
在这里插入图片描述

四、redo log 重做日志

事务日志redo log(重做日志):是Innodb存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复。比如MySQL实例挂了或宕机了,重启时,InnoDB存储引擎会使用redo log恢复数据

  • redo log是物理日志,记录页的物理修改操作:在某个数据页做了什么修改,比如对x表空间中的N数据页ZZ偏移量的地方做了AAAA更新,每当执行一个事务就会产生这样的一条或者多条物理日志
  • 保证数据的持久性:redo log会在事务提交时将日志存储到磁盘redo log file,保证日志的持久性。同时mysql会将数据写入磁盘,保证数据的持久性【在事务提交时,只要先将redo log 持久化到磁盘即可,可以不需要等到将缓存在 Buffer Pool 里的脏页数据持久化到磁盘;当系统崩溃时,虽然脏页数据没有持久化,但是redo log已经持久化,接着MySQL重启后,可以根据redo log的内容,将所有数据恢复到最新的状态】

介绍下 缓冲池与数据页的概念

  • 缓冲池(buffer pool):主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度
  • 数据页(page):是InnoDB 存储引擎磁盘管理的最小单元,每个页的大小默认为 16KB。页中存储的是行数据

MySQL中数据是以页为单位,你查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到Buffer Pool中。后续的查询都是先从Buffer Pool中找,没有命中再去硬盘加载,减少硬盘IO开销,提升性能。

更新表数据的时候,也是如此,发现Buffer Pool里存在要更新的数据,就直接在Buffer Pool里更新。然后会把在某个数据页上做了什么修改记录到重做日志缓存(redo log buffer)里,接着刷盘到redo log文件里。同时,InnoDB引擎会在适当的时候,将这个操作记录更新到磁盘里面。

redo log的更新流程如下,以一次update操作为例

在这里插入图片描述

  1. 执行Update操作
  2. 先将原始数据读从磁盘读取到内存,修改内存中的数据。
  3. 生成一条重做日志写入redo log buffer ,纪录数据被修改后的值。
  4. 当事物提交时,需要将redo log buffer中的内容刷新到redo log file。
  5. 事物提交后,也会将内存中修改的数据写入到磁盘。

4.1 redo log详解

什么是 redo log?为了方便理解,先举个来自极客时间的例子:

还记得《孔乙己》这篇文章,饭店掌柜有一个粉板,专门用来记录客人的赊账记录。如果赊账的人不多,那么他可以把顾客名和账目写在板上。但如果赊账的人多了,粉板总会有记不下的时候,这个时候掌柜一定还有一个专门记录赊账的账本

如果有人要赊账或者还账的话,掌柜一般有两种做法:

  • 一种做法是直接把账本翻出来,把这次赊的账加上去或者扣除掉;
  • 另一种做法是先在粉板上记下这次的账,等打烊以后再把账本翻出来核算。

在生意红火柜台很忙时,掌柜一定会选择后者,因为前者操作实在是太麻烦了。首先,你得找到这个人的赊账总额那条记录。你想想,密密麻麻几十页,掌柜要找到那个名字,可能还得带上老花镜慢慢找,找到之后再拿出算盘计算,最后再将结果写回到账本上。

这整个过程想想都麻烦。相比之下,还是先在粉板上记一下方便。你想想,如果掌柜没有粉板的帮助,每次记账都得翻账本,效率是不是低得让人难以忍受?

为什么需要 redo log?

为什么需要写Redo Log Buffer 和 Redo Log Flle?而不是直接持久化到磁盘?

跟上述案例类似,在 MySQL 中,如果每一次的更新要写进磁盘,这么做会带来严重的性能问题:

  • 因为 Innodb 是以页为单位进行磁盘交互的,而一个事务很可能只修改一个数据页里面的几个字节,这时将完整的数据页刷到磁盘的话,太浪费资源了!
  • 一个事务可能涉及修改多个数据页,并且这些数据页在物理上并不连续,使用随机 IO 写入性能太差

为了解决这个问题,MySQL 的设计者就用了类似掌柜粉板的思路来提升更新效率。这种思路在 MySQL 中叫 WAL(Write-Ahead Logging),意思就是:先写 redo log 日志,后写磁盘。日志和磁盘就对应上面的粉板和账本。

具体到 MySQL 是这样的:有记录需要更新,InnoDB 把记录写到 redo log 中,并更新内存中的数据页,此时更新就算完成。同时,后台线程会把操作记录更新异步到磁盘中的数据页。

PS:当需要更新的数据页在内存中时,就会直接更新内存中的数据页;不在内存中时,在可以使用 change buffer(篇幅有限,后面写文章再聊) 的情况下,就会将更新操作记录到 change buffer 中,并将这些操作记录到 redo log 中;如果此时有查询操作,则触发 merge 操作,返回更改后的记录值

有些人说 InnoDB 引擎把日志记录写到 redo log 中,redo log 在哪,不也是在磁盘上么?

对,这也是一个写磁盘的过程,但是与更新过程不一样的是,更新过程是在磁盘上随机 IO,费时。 而写 redo log 是在磁盘上顺序 IO,效率要高

PPS:redo log 的存在就是把全局的随机写,变换为局部的顺序写,从而提高效率

4.2 redo log的写入过程、刷盘时机

redo log 记录了事务对数据页做了哪些修改。它包括两部分:分别是内存中的日志缓冲(redo log buffer)和磁盘上的日志文件(redo log file)。

mysql 每执行一条 DML 语句,先将记录写入 redo log buffer,后续某个时间点再一次性将多个操作记录写到 redo log file。也就是我们上面提到的 WAL 技术。

计算机操作系统告诉我们:用户空间下的缓冲区数据是无法直接写入磁盘的。因为中间必须经过操作系统的内核空间缓冲区(OS Buffer)。

所以,redo log buffer 写入 redo logfile 实际上是先写入 OS Buffer,然后操作系统调用 fsync() 函数将日志刷到磁盘。过程如下:

在这里插入图片描述

mysql 支持三种将 redo log buffer 写入 redo log file 的时机,可以通过 innodb_flush_log_at_trx_commit 参数配置,各参数值含义如下:建议设置成1,这样可以保证MySQL 异常重启之后数据不丢失

参数值含义
0(延迟写)事务提交时不会将 redo log buffer 中日志写到 os buffer,而是每秒写入os buffer 并调用 fsync() 写入到 redo logfile 中。也就是说设置为0时 是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。
1(实时写、实时刷新)事务每次提交都会将 redo log buffer 中的日志写入 os buffer 并调用 fsync() 刷到 redo logfile 中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能差。
2(实时写、延迟刷新刷新)每次提交都仅写入到 os buffer,然后是每秒调用 fsync() 将 os buffer 中的日志写入到 redo log file。

4.3 redo log file 的结构

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

在这里插入图片描述

上图中,write pos 表示 redo log 当前记录的 LSN (逻辑序列号) 位置,一边写一遍后移,写到第 3 号文件末尾后就回到 0 号文件开头; check point 表示数据页更改记录刷盘后对应 redo log 所处的 LSN(逻辑序列号) 位置,也是往后推移并且循环的。

PS:check point 是当前要擦除的位置,它与数据页中的 LSN 应当是一致的

write pos 到 check point 之间的部分是 redo log 的未写区域,可用于记录新的记录;check point 到 write pos 之间是 redo log 已写区域,是待刷盘的数据页更改记录。

当 write pos 追上 check point 时,表示 redo log file 写满了,这时候有就不能执行新的更新。得停下来先擦除一些记录(擦除前要先把记录刷盘),再推动 check point 向前移动,腾出位置再记录新的日志。

4.4 什么是 crash-save

有了 redo log ,即在 InnoDB 存储引擎中,事务提交过程中任何阶段,MySQL 突然奔溃,重启后都能保证事务的完整性,已提交的数据不会丢失,未提交完整的数据会自动进行回滚。这个能力称为 crash-safe,依赖的就是 redo log 和 undo log 两个日志。

比如:重启 innodb 时,首先会检查磁盘中数据页的 LSN ,如果数据页的 LSN 小于日志中 check point 的 LSN ,则会从 checkpoint 开始恢复。

4.5 redo log细节

  • redo log是物理日志(并非sql执行语句 sql语句是逻辑操作),顺序写入,性能比较高
  • 重做日志是innodb存储引擎产生的
  • 重做日志由redo logo buffer和redo log file构成,即由 内存中的重做日志缓存、日志文件构成

五、补充

5.1 binlog与redolog对比、逻辑日志与物理日志

redo log 和 binlog 主要有三种不同:

  • redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
  • redo log 是物理日志(并非sql执行语句 sql语句是逻辑操作),记录的是在某个数据页上做了什么修改,比如"对XXX表空间中的YYY数据页ZZZ偏移量的地方做了AAA更新" ;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如 “给 ID=2 这一行的 age 字段加1”
  • redo log 是循环写的,空间固定会用完;binlog是可以追加写入的。追加写是指 binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

逻辑日志:可以简单理解为记录的就是sql语句

物理日志:因为mysql数据最终是保存在数据页中的,物理日志记录的就是数据页变更

5.2 update语句的执行流程

了解了binlog、redolog两种日志的概念,再来看看执行器和 InnoDB 引擎在执行 update 语句时的流程:

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

整个过程如下图所示,其中橙色框表示是在 InnoDB 内部执行的,绿色框表示是在执行器中执行的:

在这里插入图片描述

5.3 两阶段提交

在执行更新语句过程中,会记录redolog、binlog两块日志,以基本的事务为单位。

redolog在事务执行过程中可以不断写入,binlog只在提交事务时写入

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

在这里插入图片描述

由于 redo log 和 binlog 是两个独立的逻辑,如果不用两阶段提交,要么就是先写完 redo log 再写 binlog,或者采用反过来的顺序。我们看看这两种方式会有什么问题。

仍然用前面的 update 语句来做例子。假设当前 id=2 的行,字段 age 的值是 22,再假设执行update 语句过程中在写完第一个日志后,第二个日志还没有写完期间发生了 crash,会出现什么情况呢?

  1. 先写redo log 后写binlog。假设在redo log写完,binlog 还没有写完的时候,MySQL进程异常重启。由于我们前面说过的,redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 age 的值是 22。

但是 binlog 没写完就 crash 了,这时 binlog 里面并没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。

等到需要用这个binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 age 值就是 22,与原库的值不同。

  1. 先写 binlog 后写 redo log。如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,所以 age 的值是 22。但是 binlog 里面已经记录了"把从 22 改成 23" 这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 age 的值就是 23,与原库的值不同。

所以,如果不使用"两阶段提交",数据库的状态就有可能和用 binlog 恢复出来的不一致。

另外:sync_binlog 这个参数建议设置成 1,表示每次事务的binlog都持久化到磁盘,这样可以保证 MySQL 异常重启之后 binlog 不丢失

5.4 总结、使用场景

  • 二进制binlog(归档日志):是Server层生成的日志,主要用于数据备份和主从复制;
  • undolog(回滚日志):是Innodb存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和MVCC
  • 事务日志redolog(重做日志):是Innodb存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复

binlog的应用场景

  • 主从复制:在Master端开启binlog,然后将binlog 发送到各个Slave端,Slave端重放binlog从而达到主从数据一致。
  • 数据恢复:通过使用mysqlbinlog工具来恢复数据。

undolog的使用场景

  • 事务回滚
  • MVCC

redolog的使用场景

掉电等故障恢复

redo log一旦提交意味着持久化了,但是有时候需要对其进行rollback操作,那就需要undo log

主从:写数据时只写主库,在读数据时只读从库,这样即使写请求会锁表或者锁记录,也不会影响读请求的执行;

参考:

MySQL面试题(最全、超详细)—— 定位慢查询、undo log与redo log

MVCC 原理分析、MySQL是如何解决幻读的

《MySQL》系列 - 十张图详解 MySQL 日志(建议收藏)

MySQL进阶(日志)——MySQL的日志 & bin log (归档日志) & 事务日志redo log(重做日志) & undo log(回滚日志)

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

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

相关文章

一文速通stack和queue的理解与使用

CSTL之stack和queue 1.stack1.1.stack的基本概念1.2.stack的接口 2.queue2.1.queue的基本概念2.2.queue的接口 3.priority_queue3.1.priority_queue的基本概念3.2.priority_queue的接口3.3.仿函数 4.容器适配器5.deque5.1.deque的简单了解5.2.deque的优缺点 🌟&…

关于CAN(FD)转以太网详细介绍

一、功能描述 CANFD 完全向下兼容 CAN ,以下统称 CAN(FD) 。 SG-CAN(FD)NET-210 是一款用来把 CANFD 总线数据转为网口数据的设备。 网口支持 TCP Sever 、 TCP Client 、 UDP Sever 、 UDP Client 四种模式。 可以通过软件配置和 Web 网页配置。 两路…

orbbec 奥比中光相机单目及多目调用方式python代码

这篇文章会介绍使用orbbec相机的一些常用代码梯子 orbbec 奥比中光Astra相机单目及多目调用方式编译sdk调用单相机调用多相机orbbec 奥比中光Astra相机单目及多目调用方式 Orbbec相机是一个专注于深度感知和计算机视觉应用的设备,通常用于3D扫描、手势识别、增强现实(AR)以及…

力扣hot100-->滑动窗口、贪心

你好呀,欢迎来到 Dong雨 的技术小栈 🌱 在这里,我们一同探索代码的奥秘,感受技术的魅力 ✨。 👉 我的小世界:Dong雨 📌 分享我的学习旅程 🛠️ 提供贴心的实用工具 💡 记…

PBFT算法

在我的博客中对于RAFT算法也有详细的介绍,raft算法包含三种角色,分别是:跟随者( follower ),候选人(candidate )和领导者( leader )。集群中的一个节点在某一…

跨境电商代购系统独立站深度分享

在全球化日益加深的今天,跨境电商代购系统独立站作为一种新兴的电子商务模式,正逐渐成为连接全球消费者与优质商品的重要桥梁。本文将详细介绍跨境电商代购系统独立站的基本功能以及技术实现的重难点,以期为相关从业者提供一些有价值的参考和…

携程旅行 登录分析

声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 逆向分析 所有加密流程基本一样就说…

西藏酥油茶:高原上的醇香温暖

西藏酥油茶:高原上的醇香温暖 在西藏高原,有一种饮品,它不仅滋养了一代又一代的藏民,还承载着丰富的文化与历史,它就是西藏酥油茶。酥油茶,藏语称为“恰苏玛”,意为搅动的茶,是藏族人民日常生活中不可或缺的一部分,更是待客、祭祀等活动中的重要礼仪物品。 历史与文化渊源 酥…

刷题总结 回溯算法

为了方便复习并且在把算法忘掉的时候能尽量快速的捡起来 刷完回溯算法这里需要做个总结 回溯算法的适用范围 回溯算法是深度优先搜索(DFS)的一种特定应用,在DFS的基础上引入了约束检查和回退机制。 相比于普通的DFS,回溯法的优…

Antd React Form使用Radio嵌套多个Select和Input的处理

使用Antd React Form使用Radio会遇到嵌套多个Select和Input的处理&#xff0c;需要多层嵌套和处理默认事件和冒泡&#xff0c;具体实现过程直接上代码。 实现效果布局如下图 代码 <Formname"basic"form{form}labelWrap{...formItemLayoutSpan(5, 19)}onFinish{on…

Linux(Centos、Ubuntu) 系统安装jenkins服务

该文章手把手演示在Linux系统下如何安装jenkins服务、并自定义jenkins数据文件位置、以及jenkins如何设置国内镜像源加速&#xff0c;解决插件下载失败问题 安装方式&#xff1a;war包安装 阿里云提供的war下载源地址&#xff1a;https://mirrors.aliyun.com/jenkins/war/?s…

【基于无线电的数据通信链】Link 11 仿真测试

〇、废话 Link 11 仿真测试 涉及多个方面&#xff0c;包括信号仿真、协议模拟、数据链路层的仿真以及网络性能评估等。Link 11 是一种基于 HF&#xff08;高频&#xff09; 或 UHF&#xff08;超高频&#xff09; 波段的无线通信协议&#xff0c;主要用于军事通信系统中。为了…

VScode 开发 Springboot 程序

1. 通过maven创建springboot程序 输入 mvn archetype:generate 选择模板&#xff0c;一般默认选择为第 7 种方式&#xff1b; 选择之后&#xff0c;一般要你填写如下内容&#xff1a; groupId: 组织名称&#xff1b;artifactId: 项目名称&#xff1b;version: 版本&#xff0…

深入MapReduce——引入

引入 前面我们已经深入了HDFS的设计与实现&#xff0c;对于分布式系统也有了不错的理解。 但HDFS仅仅解决了海量数据存储和读写的问题。要想让数据产生价值&#xff0c;一定是需要从数据中挖掘出价值才行&#xff0c;这就需要我们拥有海量数据的计算处理能力。 下面我们还是…

springfox-swagger-ui 3.0.0 配置

在3.0中&#xff0c;访问地址URL变了。 http://地址:端口/项目名/swagger-ui/ SpringBoot maven项目引入 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>3.0.0</version> </…

如何解压7z文件?8种方法(Win/Mac/手机/网页端)

7z 文件是一种高效的压缩文件格式&#xff0c;由 7 - Zip 软件开发者所采用。它运用独特的压缩算法&#xff0c;能显著缩小文件体积&#xff0c;便于存储与传输各类数据&#xff0c;像软件安装包、大型资料集等。但要使用其中内容&#xff0c;就必须解压&#xff0c;因为处于压…

Spring Boot 邂逅Netty:构建高性能网络应用的奇妙之旅

一、引言 在当今数字化时代&#xff0c;构建高效、可靠的网络应用是开发者面临的重要挑战。Spring Boot 作为一款强大的 Java 开发框架&#xff0c;以其快速开发、简洁配置和丰富的生态支持&#xff0c;深受广大开发者喜爱。而 Netty 作为高性能、异步的网络通信框架&#xff…

[STM32 - 野火] - - - 固件库学习笔记 - - -十一.电源管理系统

一、电源管理系统简介 电源管理系统是STM32硬件设计和系统运行的基础&#xff0c;它不仅为芯片本身提供稳定的电源&#xff0c;还通过多种电源管理功能优化功耗、延长电池寿命&#xff0c;并确保系统的可靠性和稳定性。 二、电源监控器 作用&#xff1a;保证STM32芯片工作在…

从 Web2 到 Web3:技术演进中的关键变革

随着互联网的快速发展&#xff0c;Web 技术经历了从 Web1 到 Web2&#xff0c;再到当前热议的 Web3 的演变。每一次技术迭代不仅仅是技术本身的升级&#xff0c;更代表着对社会、经济和文化的深刻影响。本文将带你走过 Web2 到 Web3 的技术演进&#xff0c;探讨其中的关键变革&…

Android实战经验篇-玩转Selinux(详解版)

列文章转如下链接&#xff1a; Android Display Graphics系列文章-汇总 Android实战经验篇-系列文章汇总 本文主要包括部分&#xff1a; 一、Selinux概述 1.1 SELinux是什么&#xff1f; 1.2 自主访问控制&#xff08;DAC&#xff09; 1.3 强制访问控制&#xff08;MAC&…