MySQL 日志体系解析:保障数据一致性与恢复的三位英雄:Redo Log、Undo Log、Bin Log

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL 日志体系解析:保障数据一致性与恢复的三位英雄:Redo Log、Undo Log、Bin Log

前言

MySQL Redo Log、Undo Log、Bin Log 三大日志与数据库事务相挂钩,之前在介绍 MySQL 事务时,提及到了它的四大特性,原子性、一致性、隔离性、持久性

  1. 原子性:由 MySQL Undo Log 日志来实现,并保证事务的原子性操作
  2. 隔离性:由隔离级别、锁来保证
  3. 持久性:通过 InnoDB 存储引擎 Redo Log 日志来实现

Redo Log

Redo Log 日志是 InnoDB 存储引擎中的日志文件,用它来保证事务的持久化操作,以下是 Redo Log 几大作用

  1. 数据持久性保证:Redo Log 记录了 InnoDB 存储引擎在执行事务期间所做的修改操作 > 插入、更新、删除操作等。通过将这些操作记录到 Redo Log 日志中,即使数据库发生异常关闭或重启,之前的记录也不会丢失,叫做 crash-safe
  2. 事务持久性保证:在提交事务之前,InnoDB 存储引擎会先将记录写入到 Redo Log 日志中,并更新对应的内存缓冲区,同时会在合适的时机将修改后的记录刷写到磁盘中去。即使提交事务之前,发生了故障,MySQL 还可以通过 Redo Log 来重新执行未完成的事务,确保事务持久性
  3. 故障恢复:当数据库异常关闭或重启时,MySQL 可以利用 Redo Log 来进行故障恢复
  4. 提高性能:Redo Log 设计采用了顺序写的方式,相比于随机写入,顺序写入 Redo Log 的性能更高

Redo Log 写入执行过程

在操作系统中分为两种空间:用户空间、内核空间,最下面是磁盘空间

如上图,当更新完数据,一旦提交先将操作记录写入到 Redo Log 中,会保存到 Log Buffer 空间;随即 Log Buffer 会将数据写入到 OS Buffer,OS Buffer 会触发系统调用 fsync() 异步写入到磁盘中

Redo Log 写入方式

在 MySQL 中,Redo Log 写入方式可以通过 innodb_flush_log_at_trx_commit 参数进行配置,该参数有三个可选的取值:0、1、2,分别代表不同的写入方式,默认值为 1,通过以下 SQL 查看

show VARIABLES like 'innodb_flush_log_at_trx_commit';
  1. innodb_flush_log_at_trx_commit = 0: 表示异步写入方式,在每个事务提交时,Redo Log 写入磁盘操作被延迟,并且可能会与多个事务的写入操作组合在一起批量写入;这种方式可以提高较高的性能,但会存在一定的数据丢失风险,因为在发生故障时,尚未写入磁盘的 Redo Log 日志可能会丢失
  2. innodb_flush_log_at_trx_commit = 1: 表示同步写入方式,在每个事务提交时,Redo Log 写入操作会被立马刷写到磁盘中;这种方式可以提高最高的数据安全性,因为在事务提交后,Redo Log 已经持久化到磁盘中,即使发生故障,也可以保证不丢失任何已提交的事务

若提交的频率比较高,那么每次写入到磁盘都是一次磁盘 IO,这样产生的 IO 次数肯定是很多的,但相对于其他两种方式,每次都能保证写入到磁盘中

  1. innodb_flush_log_at_trx_commit = 2: 表示延迟写入方式,在每个事务提交时,Redo Log 写入操作被延迟,但在事务提交后的一定时间内会将数据刷写到磁盘中;这种方式折中了性能、数据安全性,可以提高很好的性能和一定程度的保护

0、2 这两种方式在批量提交时效率比较快,一秒钟可能积累的事务数会很多,但是数据存在不安全,可能会丢失一秒钟的数据

总而言之,数据安全性、性能两者不能同时都保证,选择适当的配置值需要根据应用程序的需求以及对数据安全性的要求两者进行 Trade Off!

在 MySQL 中,还有一些常用参数可以支持 Redo Log 配置,如下:

  1. innodb_log_file_size:该参数用于配置每个 Redo Log 文件大小,以字节为单位,较大的 Redo Log 文件大小可以减少 Redo Log 切换的频率,从而提升性能,默认值为 50 MB
  2. innodb_log_files_in_group:该参数用于配置 Redo Log 文件数量,增加 Redo Log 文件数量可以增加 Redo Log 并发写入能力,从而提交整体性能,默认值为 2
  3. innodb_log_buffer_size:该参数用于配置 Redo Log 缓冲区大小,以字节为单位,增加缓冲区大小可以提高 Redo Log 写入性能,但同时也会占用更多的内存,默认值为 16 MB

这些参数可以通过修改 MySQL 配置文件(my.cnf 或 my.ini)来进行设置,在进行更改之前建议备份数据库。不正确的参数配置可能会对数据库的性能、稳定性产生影响,并测试环境中进行充分测试和评估

Undo Log

Undo Log 日志是 InnoDB 存储引擎中的日志文件,用它来保证事务的原子性操作

在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方成为 Undo Log)然后进行修改操作,若出现错误或者用户执行了 ROLLBACK 语句,系统可以利用 Undo Log 中的备份数据恢复到事务开始之前的状态

Undo Log 主要作用是支持数据库的事务回滚、MVCC(多版本并发控制)详细内容如下:

  1. 事务回滚:当发生事务回滚时,MySQL 可以使用 Undo Log 来撤销已经提交的事务所做的修改操作,将数据恢复到事务开始之前的状态。通过 Undo Log,MySQL 能够保证事务的原子性,即事务要么全部成功,要么全部回滚,不会出现部分提交的情况

Undo Log 是逻辑日志,可以理解为

1、当 delete 一条记录时,Undo Log 会生成一条对应的 insert 记录

2、当 insert 一条记录时,Undo Log 会生成一条对应的 delete 记录

3、当 update 一条记录时,Undo Log 会生成相反的 update 记录

  1. MVCC 支持:MySQL 使用 Undo Log 来实现 MVCC 机制,以支持并发事务之间的隔离性,在 MVCC 中,每个事务都能够看到一致性的数据快照,而不会被其他事务的修改所干扰(结合事务的隔离级别)
  2. 数据版本管理:Undo Log 记录了事务修改操作的逆操作日志,因此可以用来回滚事务、撤销数据的修改,通过维护不同版本的数据,MySQL 能够使得读取、写入操作可以同时进行,提高数据库的并发性能
  3. 回收空间:当事务提交后,Undo Log 对应的数据操作已经生效,并且数据库的数据文件已经发生了相应修改,此时,Undo Log 记录的旧版本数据可以被回收空间,释放占用的资源

Bin Log

Bin Log(二进制日志)日志是 MySQL Server 层面的日志文件,主要用于作 MySQL 功能层面的事情,同时它也可以用来作数据的复制、恢复、故障恢复工作

Bin Log 几个主要的作用如下:

  1. 数据复制:Bin Log 被用于数据库的主从复制,当启用了主从复制时,主数据库会将其接收到的修改操作记录到 Bin Log 中,然后从数据库通过读取 Bin Log 中数据进行重放,从而将主数据库的修改操作记录同步到从数据库,这样可以实现数据的复制、不同节点数据之间的同步
  2. 数据恢复:Bin Log 可以用于恢复数据,尤其在灾难恢复、误操作时非常有用;通过将 Bin Log 中操作重新执行,可以将数据库恢复到待定的时间点或待定的事务状态,Bin Log 对于数据额恢复、修复非常重要
  3. 故障恢复:当数据库发生故障、崩溃、宕机时,可以利用 Bin Log 来进行故障恢复,通过重新执行 Bin Log 中未提交的事务,可以恢复到故障发生前的状态,以此来确保数据的一致性、完整性
  4. 数据审计、追踪:Bin Log 记录了数据库所有修改操作,包括数据插入、更新、删除,这可以用来做数据审计、追踪,了解操作数据库的历史记录,跟踪特定数据的修改记录,以及满足合规、安全性要求

需要注意的是,Bin Log 是基于事务的日志,只记录对数据的修改操作,而不包括查询操作

Bin Log、Redo Log 之间的区别

  1. 作用范围不同:Redo Log 是 InnoDB 存储引擎独有的,Bin Log 是所有存储引擎都可以使用的
  2. 存储位置、形式不同

Bin Log 以文件的形式存储在磁盘上,通常会有多个 Bin Log 文件组成一个序列,每个文件都有一个递增的序号。Bin Log 文件是追加写入的,新的修改操作会不断追加到最新的 Bin Log 文件中

Redo Log 以循环写入的方式存储在磁盘上,通常会有多个 Redo Log 文件组成一个循环队列。当 Redo Log 写入位置到达文件末尾时,会回到文件的起始位置再次进行循环写入

  1. 写入时机、方式不同

Bin Log 写入是在事务提交时进行的,即在事务完成之后将修改操作记录到 Bin Log 中。Bin Log 写入可以是同步或异步的,可以通过参数配置来调整

Redo Log 写入是在事务执行期间进行的,即在事务进行修改操作时就会将相应的 Redo Log 记录写入到 Redo Log 文件中。Redo Log 写入是顺序写入的,采用追加写的方式

Bin Log 写入方式

Bin Log 写入方式可以通过 sync_binlog 参数进行配置,它有三种取值,如下:

  1. sync_binlog = 0:表示异步写入方式,即当事务提交后不等待将 Bin Log 数据写入到磁盘,而是将其缓存到内存中,从而提高写入性能
  2. sync_bin_log = 1:表示同步写入方式,即当事务提交后等待 Bin Log 数据写入到磁盘成功后,才返回给客户端结果,降低了写入性能提高了数据安全性
  3. sync_binlog = N(N > 1):表示每 N 个事务同步写入一次,当 N > 1 时,MySQL 将使用批量写入的方式,每处理 N 个事务后将 Bin Log 数据批量写入磁盘,并等待确认写入完成返回,折中了性能、数据安全性,减少了频繁的磁盘写入操作

Bin Log 恢复误删数据

首先通过 Bin Log 来恢复误删除的数据,要确认 Bin Log 是否开启,若未开启,可能你丢失的数据就很难溯源了

SHOW VARIABLES LIKE 'log_bin';

通过以下这种方式,开启 Bin Log

  1. 找到 MySQL 配置文件:my.cnf 或 my,ini,在 Linux 系统中,一般文件放在 /etc 目录下
  2. vim 打开配置文件,追加内容如下:
[mysqld]
# 服务 id,开启 bin log 要标识服务端
server-id=1
# 开启 Bin Log,二进制文件基本存储目录 > /var/lib/mysql/binlog
log_bin=/var/lib/mysql/binlog

:wq! 保存后退出,修改存储目录权限 > chomod 755 /var/lib/mysql/binlog

  1. 配置文件修改后保存好,执行重启 MySQL 命令:sudo systemctl restart mysqld,等待数据库服务重启以后,再次执行 SHOW VARIABLES LIKE 'log_bin'; 命令观察 Bin Log 是否开启成功

确认好 Bin Log 已开启好以后,操作一条删除语句,比如:

DELETE from emp where empno in(7900,7902);

然后在 /var/lib/mysql 目录下就能看到 bin log 日志文件了

通过以下命令来进行观察,将二机制转为 SQL 语句导出在本地文件 > output.sql,如下:

# --start-datetime="2023-06-13 18:28:00" --stop-datetime="2023-06-13 18:34:00"
# 通过时间点范围导出部分数据,而不是全量数据,便于快速定位到需要的数据部分
mysqlbinlog --no-defaults --base64-output=decode-rows  -v binlog.000001 > output.sql

最终,通过观察文件内容找出了原始的数据,可以对它进行恢复操作

二阶段提交>数据更新

如上图,数据更新执行过程分为以下几点

  1. 执行器先从存储引擎获取数据,若在内存中直接返回,否则先从 B+ 树中查询后再返回
  2. 执行器获取数据后返回,进行数据的修改操作,然后调用存储引擎重新写入数据
  3. 存储引擎将数据更新到内存中,同时写数据到 Redo Log 中,当前处于 prepare 阶段,并通知执行器去继续向下执行,随时可以进行操作
  4. 执行器生成这个更新操作的 Bin Log
  5. 执行器调用存储引擎的事务机制提交数据,当前处于 commit 阶段,存储引擎把刚刚写完的 Redo Log 改为 commit 状态

为什么 Redo Log 要采用两阶段提交,假设不使用两阶段,举例场景如下:

1、先写完 Redo Log 后再写 Bin Log

属性:name,由 choshim -> vnjohn

假设在 Redo Log 写完,Bin Log 还未写完时,MySQL 进程异常重启;由于前面所提及到的,Redo Log 写完之后,即使系统崩溃了,仍然能够把数据恢复回来,所以恢复后 name 值变为 choshim,但是由于 Bin Log 没写完就 crash 了,这时候 Bin Log 里面讲究没有这条语句;因此,在之后备份日志的时候,Bin Log 存起来的数据里面就没有这条语句;最后,你会发现,若使用这个 Bin Log 来恢复临时库的话,由于这条语句的 Bin Log 丢失,临时库就会少了这一次数据更新,恢复出来的这一条数据 name 值为 choshim,与原有库中的值不同

2、先写 Bin Log 后再写 Redo Log

属性:name,由 choshim -> vnjohn

假设在 Bin Log 写完之后 crash 了,由于 Redo Log 还没写,崩溃恢复这个事务无效,所以这一条数据 name 属性值为 choshim;但 Bin Log 里面已经记录了 “把 name 从 choshim 改为 vnjohn” 日志;所以,之后用 Bin Log 来进行恢复时就会多出了一条更新操作的事务出来,恢复出来的这一条数据 name 属性值为 vnjohn,与原有库值不同

因为以上这两种问题,谁先写谁后写都会发生问题,所以要解决这种一致性问题,就不得已要采取分阶段的方式来保证事务的完整性

如上图在时刻 A 的地方,也就是写入 Redo Log 处于 prepare 阶段之后、写 Bin Log 之前,发生了系统崩溃 crash,由于此时 Bin Log 还没写入,Redo Log 也还没进行提交;所以崩溃恢复时,这个事务会进行回滚,同时,Bin Log 还没写入,所以也不会传给备用库

若在 Redo Log 里面的事务是完整的,也就是有了 commit 标识,则直接提交;若 Redo Log 里面的事务只有完整的 prepare 阶段,则判断对应事务的 Bin Log 是否存在并完整

1、若事务的 Bin Log 完整,则提交事务

2、若事务的 Bin Log 不完整,则回滚事务

若是在时刻 B 发生 crash,在崩溃恢复过程中事务是会被提交的

PS:两阶段提交的最后一阶段操作本身是不会失败的,除非是系统或硬件发生了错误,所以也就不再需要回滚

总结

该篇博文从浅入深的讲解了 MySQL 中三大日志 > Redo Log、Undo Log、Bin Log 三大日志体系,Redo Log、Undo Log 是 InnoDB 存储引擎内的日志,Bin Log 是 MySQL Server 层面的日志,接着仔细说明了它们各自的作用,包括了写入的执行过程、写入的方式,实战方面,演示了如何使用 Bin Log 恢复误删的数据,最后,分析了为什么要采用两阶段提交方式来完成 Redo Log、Bin Log 记录以及数据更新!

MySQL 专栏高质量博文如下:

MySQL 内置的监控工具介绍及使用篇

构建优化之城:MySQL 数据建模、数据类型优化与索引常识全面解析

MySQL 数据结构优化与索引细节解析:打造高效数据库的优化秘笈

MySQL 数据访问与查询优化:提升性能的实战策略和解耦优化技巧

深度解析 MySQL 事务、隔离级别和 MVCC 机制:构建高效并发的数据交响乐

如果觉得博文不错,关注我 vnjohn,后续会有更多实战、源码、架构干货分享!

推荐专栏:Spring、MySQL,订阅一波不再迷路

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!



目录
相关文章
|
2月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
429 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
22天前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
|
28天前
|
存储 SQL 关系型数据库
mysql 的ReLog和BinLog区别
MySQL中的重做日志和二进制日志是确保数据库稳定性和可靠性的关键组件。重做日志主要用于事务的持久性和原子性,通过记录数据页的物理修改信息来恢复未提交的事务;而二进制日志记录SQL语句的逻辑变化,支持数据复制、恢复和审计。两者在写入时机、存储方式及配置参数等方面存在显著差异。
|
11天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
54 2
|
28天前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
1月前
|
存储 监控 安全
什么是事件日志管理系统?事件日志管理系统有哪些用处?
事件日志管理系统是IT安全的重要工具,用于集中收集、分析和解释来自组织IT基础设施各组件的事件日志,如防火墙、路由器、交换机等,帮助提升网络安全、实现主动威胁检测和促进合规性。系统支持多种日志类型,包括Windows事件日志、Syslog日志和应用程序日志,通过实时监测、告警及可视化分析,为企业提供强大的安全保障。然而,实施过程中也面临数据量大、日志管理和分析复杂等挑战。EventLog Analyzer作为一款高效工具,不仅提供实时监测与告警、可视化分析和报告功能,还支持多种合规性报告,帮助企业克服挑战,提升网络安全水平。
|
2月前
|
关系型数据库 MySQL 数据库
【赵渝强老师】MySQL的binlog日志文件
MySQL的binlog日志记录了所有对数据库的更改操作(不包括SELECT和SHOW),主要用于主从复制和数据恢复。binlog有三种模式,可通过设置binlog_format参数选择。示例展示了如何启用binlog、设置格式、查看日志文件及记录的信息。
168 6
|
2月前
|
存储 SQL 关系型数据库
mysql 的ReLog和BinLog区别
MySQL中的重做日志(Redo Log)和二进制日志(Binary Log)是两种重要的日志系统。重做日志主要用于保证事务的持久性和原子性,通过记录数据页的物理修改信息来恢复未提交的事务更改。二进制日志则记录了数据库的所有逻辑变化操作,用于数据的复制、恢复和审计。两者在写入时机、存储方式、配置参数和使用范围上有所不同,共同确保了数据库的稳定性和可靠性。
|
2月前
|
存储 监控 安全
什么是日志管理,如何进行日志管理?
日志管理是对IT系统生成的日志数据进行收集、存储、分析和处理的实践,对维护系统健康、确保安全及获取运营智能至关重要。本文介绍了日志管理的基本概念、常见挑战、工具的主要功能及选择解决方案的方法,强调了定义管理目标、日志收集与分析、警报和报告、持续改进等关键步骤,以及如何应对数据量大、安全问题、警报疲劳等挑战,最终实现日志数据的有效管理和利用。
142 0
|
SQL 数据采集 监控
基于日志服务数据加工分析Java异常日志
采集并脱敏了整个5月份的项目异常日志,准备使用日志服务数据加工做数据清洗以及分析。本案例是基于使用阿里云相关产品(OSS,RDS,SLS等)的SDK展开自身业务。需要对异常日志做解析,将原始日志中时间、错误码、错误信息、状态码、产品信息、请求方法、出错行号提取出来。然后根据提取出来的不同产品信息做多目标分发处理。对清洗后的数据做异常日志数据分析。
824 0
基于日志服务数据加工分析Java异常日志

推荐镜像

更多