【MySQL】 ---- binlog、redo log和undo log

binlog、redo log和undo log

一、日志概念

日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。本文重点关注二进制日志(binlog)和事务日志(包括redo log和undo log)

二、binlog

1. 概念

binlog用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。binlog是mysql的逻辑日志,并且由Server层进行记录,使用任何存储引擎的mysql数据库都会记录binlog日志。

MySQL 的二进制日志 binlog 记录了所有的 DDL 和 DML 语句(除了数据查询语句select、show等),以事件形式记录。

在这里插入图片描述

2. 使用场景

binlog的主要使用场景有两个,分别是主从复制数据恢复

  • 主从复制: 在Master端开启binlog,然后将binlog发送到各个Slave端,Slave端重放binlog从而达到主从数据一致

    主从复制原理:

    主要涉及三个线程: binlog线程、I/O线程和SQL线程

    • binlog 线程 :负责将主服务器上的数据更改写入二进制日志(Binary log)中
    • I/O 线程 :负责从主服务器上读取二进制日志,并写入从服务器的中继日志(Relay log)
    • SQL 线程 :负责读取中继日志,解析出主服务器已经执行的数据更改并在从服务器中重放(Replay)。

    在这里插入图片描述

三、redo log

1. 概念

redo log包括两部分:

  • 内存中的日志缓冲(redo log buffer)

  • 磁盘上的日志文件(redo log file)

mysql每执行一条DML语句,先将记录写入redo log buffer,后续某个时间点再一次性将多个操作记录写到redo log file。这种先写日志,再写磁盘的技术就是MySQL里经常说到的WAL(Write-Ahead Logging) 技术。

2. 使用场景

redo log适用于崩溃恢复(crash-safe)

MySQL的innoDB存储引擎,使用Redo log保证了事务的持久性

防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性

3. 事务的持久化实现(redo log保证)

  • 步骤1:begin;
  • 步骤2:insert into t1 …r
  • 步骤3:insert into t2 …
  • 步骤4:commit;

Alt

redo log 的写入拆成了两个步骤,preparecommit,这就是"两阶段提交”。

为什么要采用两阶段提交呢?

实际上,两阶段提交是分布式系统常用的机制。MySQL使用了两阶段提交后,也是为了保证事务的持久性。

Redo log 和binlog 有一个共同的数据字段,叫 XID,崩溃恢复的时候,会按顺序扫描 redo log。

  • 假设在写入binlog前系统崩溃,那么数据库恢复后顺序扫描 redo log,碰到只有 parepare、而没有 commit 的 redo log,就拿着 XID 去 binlog 找对应的事务,而且binlog也没写入,所以事务就直接回滚了。
  • 假设在写入binlog之后,事务提交前数据库崩溃,那么数据库恢复后顺序扫描 redo log,碰到既有 prepare、又有 commit 的 redo log,就直接提交,保证数据不丢失。

4. redo log刷盘策略

如前面提到的例子中, 事务要往两个表中插入记录,插入数据的过程中,生成的日志都得先写入redo log buffer ,等到commit的时候,才真正把日志写到 redo log 文件。(当然,这里不绝对,因为redo log buffer可能因为其他原因被迫刷新到redo log)。

而为了确保每次日志都能写入日志文件,在每次将重做日志缓冲 写入 重做日志文件后,InnoDB存储引擎都需要调用一次fsync操作,确保写入了磁盘。

在这里插入图片描述

在计算机操作系统里面, 用户空间(user space) 下的缓冲区数据一般无法直接写入磁盘, 必须经过操作系统内核空间(kernel space)缓冲区(OS buffer). 因此, redo log buffer 写入 redo log file实际上先写入OS buffer, 然后通过系统调用fsync()将其刷盘到redo log file.

Mysql 支持三种将redo log buffer 刷盘到 redo log file 的策略, 可以通过innodb_flush_log_at_trx_commit参数进行配置:

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

在这里插入图片描述

四、undo log

1. 概念

undo log主要记录了数据的逻辑变化,比如一条INSERT语句,对应一条DELETE的undo log,对于每个UPDATE语句,对应一条相反的UPDATE的undo log,这样在发生错误时,就能回滚到事务之前的数据状态。同时,undo log也是MVCC(多版本并发控制)实现的关键

2. 使用场景

  • undo log保证了事务的原子性。

  • 保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读

3. 事务原子性的实现(undo log保证)

事务原子性概念

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

如何实现?

InnoDB实现回滚,靠的是undo log:当事务对数据库进行修改时,InnoDB会生成对应的undo log;如果事务执行失败导致事务需要回滚,就利用undo log中的信息将数据回滚到修改之前的样子。

undo log 与redo log区别?

  • 两个日志文件其实都能看作是一种对数据的恢复操作,redo log恢复事务导致的数据页的修改,而undo log能够恢复数据记录到某个特定的版本

  • redo log是一种物理日志(数据页的修改),而undo log是一种逻辑日志(数据记录)

五、redo log和binlog区别

redo logbinlog
文件大小redo log的大小是固定的。binlog可通过配置参数 max_binlog_size设置每个binlog文件的大小。
实现方式redo logInnoDB引擎层实现的,并不是所有引擎都有。binlogServer 层实现的,所有引擎都可以使用 binlog日志
记录内容redo log记录了物理日志,是针对每个数据页的修改binlog是一种逻辑日志,记录对应的SQL语句, 比如“给 ID=2 这一行的 c 字段加 1 ”
记录方式redo log 采用循环写的方式记录,当写到结尾时,会回到开头循环写日志。binlog通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上
适用场景redo log适用于崩溃恢复(crash-safe)binlog适用于主从复制和数据恢复

参考:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值