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 语句如下:

html 复制代码
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阶段。

Prepare阶段
  • 在这个阶段,事务开始后,InnoDB会将修改的数据页的变化信息写入到redo log buffer中。
  • 同时,会将事务的XID(内部XA事务的ID)写入到redo log中,并将redo log对应的事务状态设置为prepare。
  • 根据配置(如innodb_flush_log_at_trx_commit的值),可能在这个阶段就将redo log buffer中的内容刷新到磁盘上的redo log文件中,以确保数据的持久性。
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, 不完整就回滚事务。

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

相关推荐
woshilys22 分钟前
sql server 查询对象的修改时间
运维·数据库·sqlserver
Hacker_LaoYi22 分钟前
SQL注入的那些面试题总结
数据库·sql
建投数据1 小时前
建投数据与腾讯云数据库TDSQL完成产品兼容性互认证
数据库·腾讯云
LCG元1 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
Hacker_LaoYi2 小时前
【渗透技术总结】SQL手工注入总结
数据库·sql
岁月变迁呀2 小时前
Redis梳理
数据库·redis·缓存
独行soc2 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍06-基于子查询的SQL注入(Subquery-Based SQL Injection)
数据库·sql·安全·web安全·漏洞挖掘·hw
你的微笑,乱了夏天3 小时前
linux centos 7 安装 mongodb7
数据库·mongodb
工业甲酰苯胺3 小时前
分布式系统架构:服务容错
数据库·架构
独行soc4 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍08-基于时间延迟的SQL注入(Time-Based SQL Injection)
数据库·sql·安全·渗透测试·漏洞挖掘