MYSQL--binlog和redo log

前言

MySQL日志

  MySQL日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中比较重要的就是二进制日志binlog(归档日志)、事务日志redo log(重做日志)和undo log(回滚日志)。

      这篇文章主要来讲解binlog和redo log

redo log

一、定义

  • 定义:Redo Log是InnoDB存储引擎特有的日志,用于记录数据页的物理变化,即数据在磁盘上的修改。
  • 作用
    • 保证事务的持久性:在数据库崩溃或意外关闭时,通过Redo Log可以恢复未提交的事务,确保数据的一致性。
    • 提高写性能:采用WAL(Write-Ahead Logging)技术,即先写日志,再写磁盘,减少了磁盘I/O操作的次数和延迟。

二、记录内容

        Redo Log:记录的是数据页的物理变化,即数据在磁盘上的实际修改。它包含了事务在数据页上的修改细节,但不包含具体的SQL语句。

三、存储方式

  • Redo Log
    • 以循环方式记录,日志文件达到一定大小后会循环覆盖旧的日志。
    • 日志文件以文件组的形式出现,包含多个日志文件,采用环形数组形式进行循环写入。

四、生命周期

  • Redo Log
    • 生命周期较短,主要用于在短期内确保数据的持久性和一致性。
    • 事务提交后的数据会最终被写入数据文件,而Redo Log会被清理和循环使用。

五、应用场景

  • Redo Log
    • 主要用于数据库的崩溃恢复,确保事务的持久性和一致性。

Binlog

一、定义

  • 定义:Binlog是MySQL数据库的二进制日志,记录了所有对数据库造成修改的SQL语句,如INSERT、UPDATE、DELETE等。
  • 作用
    • 数据复制和同步:主要用于主从复制(replication),使得从库可以通过重放Binlog来跟上主库的变化。
    • 数据恢复:在数据丢失时,通过Binlog可以将数据库恢复到某个时间点。

二、记录内容

  • Binlog:记录的是逻辑变化,即SQL语句本身。它记录了所有对数据库造成修改的SQL语句,以及这些语句的执行时间等信息。

三、存储方式

  • Binlog
    • 以二进制格式记录,使得其体积较小,并且可以高效地重放。
    • Binlog文件会根据配置进行轮转,生成多个日志文件,以便于管理和恢复。

四、生命周期

  • Binlog
    • 通常会在一定时间后被删除,具体时间依据数据库配置而定。
    • 在数据恢复或主从复制过程中,Binlog会被重放以恢复数据或同步数据。

五、应用场景

  • Binlog
    • 主要用于数据复制和同步,以及数据恢复(如恢复到某个特定时间点)。

具体应用讲解

以上就是一条查询 sql 的执行流程,那么接下来我们看看一条更新语句如何执行的呢?sql 语句如下:

update tb_student A set A.age='19' where A.name=' 张三 ';

        给张三修改下年龄。其实条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,MySQL 自带的日志模块式 binlog(归档日志) ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 redo log(重做日志),我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下:

  • 先查询到张三这一条数据,如果有缓存,也是会用到缓存。

  • 然后拿到查询的语句,把 age 改为 19,然后调用引擎 API 接口,写入这一行数据,InnoDB 引擎把数据保存在内存中,同时记录 redo log,此时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,随时可以提交。

  • 执行器收到通知后记录 binlog,然后调用引擎接口,提交 redo log 为提交状态。

  • 更新完成。

为什么要用两个日志呢?

        这是因为最开始 MySQL 并没与 InnoDB 引擎( InnoDB 引擎是其他公司以插件形式插入 MySQL 的) ,MySQL 自带的引擎是 MyISAM,但是我们知道 redo log 是 InnoDB 引擎特有的,其他存储引擎都没有。

        这就导致会没有 crash-safe 的能力(crash-safe 的能力即使数据库发生异常重启,之前提交的记录都不会丢失),binlog 日志只能用来归档。

        并不是说只用一个日志模块不可以,只是 InnoDB 引擎就是通过 redo log 来支持事务的。

redo logbinlog谁先写呢?

  • 先写 redo log 直接提交,然后写 binlog,假设写完 redo log 后,机器挂了,binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 binlog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。

  • 先写 binlog,然后写 redo log,假设写完了 binlog,机器异常重启了,由于没有 redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。

通过解释可以看到不管谁先写都会产生问题,那么是怎么解决的呢?

        简单来说我们通常是先写redo log,等写完binglog 后,再提交redo log,数据不一致的问题下面有详细解释

怎么解决先redo log的数据不一致的问题?

先写redo log解决不一致问题是引入prepare 预提交状态

        Redo Log的提交过程可以概括为两个阶段:Prepare阶段和Commit阶段。

  1. Prepare阶段
    • 在这个阶段,事务开始后,InnoDB会将修改的数据页的变化信息写入到redo log buffer中。
    • 同时,会将事务的XID(内部XA事务的ID)写入到redo log中,并将redo log对应的事务状态设置为prepare。
    • 根据配置(如innodb_flush_log_at_trx_commit的值),可能在这个阶段就将redo log buffer中的内容刷新到磁盘上的redo log文件中,以确保数据的持久性。
  2. Commit阶段
    • 当事务提交时,MySQL的执行器会处理binlog,将事务的修改以SQL语句的形式写入到binlog中。
    • Binlog写入成功后,InnoDB会调用引擎的提交事务接口,将redo log的状态从prepare更改为commit。
    • 这一步并不需要将redo log的状态立即刷新到磁盘上,因为只要binlog写磁盘成功,就算redo log的状态还是prepare也没有关系,因为redo log中的信息已经足够用于恢复数据。
    • 但是,如果配置了innodb_flush_log_at_trx_commit=1,那么在事务提交时,InnoDB还是会将redo log buffer中的内容刷新到磁盘上,以确保数据的持久性。

        如果采用 redo log 两阶段提交的方式就不一样了,写完 binglog 后,然后再提交 redo log 就会防止出现上述的问题,从而保证了数据的一致性。

那么问题来了,有没有一个极端的情况呢?假设 redo log 处于预提交状态,binglog 也已经写完了,这个时候发生了异常重启会怎么样呢?

这个就要依赖于 MySQL 的处理机制了,MySQL 的处理过程如下:

  • 判断 redo log 是否完整,如果判断是完整的,就立即提交。

  • 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。

这样就解决了数据一致性的问题。

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值