详解MySQL事务日志redo log

 更新时间:2023年07月14日 11:08:58   作者:JAVA旭阳  
你知道MySQL 中是如何保证数据不丢失的吗,即便是MySQL发生异常重启了,数据也可以恢复,你了解MySQL产生的事务日志redo log是干嘛的吗,明白它的工作机制吗,本文就给大家详细讲解MySQL事务日志redo log

redo log介绍

redo log又叫“重做日志”,是存储引擎层 (innoDB) 生成的日志,记录的是"物理级别"上的页修改操作,比如页号x,偏移量y写入了'z'数据,主要目的为了保证数据不丢失,当MySQL发生宕机的时候,可以利用redo log日志进行数据恢复,如下图所示。

默认的redo log日志文件为ib_logfile0, ib_logfile1,如下图:

那想过为什么要"多此一举"先写入到redo log磁盘文件中,然后再落到数据库表中?而不直接落到数据库表中?

主要是因为顺序IO性能远高于随机IO。

数据在MySQL中存储是以页为单位,事务中的数据可能遍布在不同的页中,如果直接写入到对应的页中,是随机IO写入。

redo log是通过顺序IO"追加"的方式写入到文件末尾,而且写入的内容也是物理日志,比如比如,某个事务将系统表空间中第10号页面中偏移量为 100 处的那个字节的值 1 改成 2等信息,日志占用空间也很小。

redo log整体流程

事务在写入到数据库中涉及到redo log的整体流程如下图所示:

性能不够,缓存来凑。由于CPU的性能远远大于磁盘,为了消除这个鸿沟,引入了两个缓存,Buffer Poolredo log bufferBuffer Pool用来存放各种操作,比如写入数据时,先写到内存中,然后由后台线程再刷写到磁盘。redo log buffer用来存放重做日志,后续刷到磁盘中。

  • 先将原始数据从磁盘中读入到Buffer Pool
  • 修改Buffer Pool中的数据
  • 生成一条重做日志并写入redo log buffer,记录数据修改后的值
  • 当事务提交时,将redo log buffer中的内容追加磁盘中的redo log文件中
  • 将磁盘日志文件redo log file 内容刷到数据库表中

上面流程中这种先写日志,再写磁盘,只有日志写入成功,才算事务提交成功的技术思想在MySQL也叫做WAL技术 (Write-Ahead Logging)。

redo log落盘策略

事务的日志是先写入到redo log buffer 中是很快的,那如何保证redo log buffer中的信息高效的落到磁盘日志文件中呢?

  • redo log buffer不是直接将日志内容刷盘到redo log file中。
  • redo log buffer内容先刷入到操作系统的文件系统缓存 (page cache)中去,这个过程很快,而且整个系统宕机概率相对MySQL会小很多。
  • 最后,日志内容会从操作系统的文件系统缓存中刷到磁盘的日志文件中,至于什么时候触发这个动作,MySQL的innoDB引擎提供了3种策略可选。

InnoDB引擎提供了 innodb_flush_log_at_trx_commit 参数,该参数控制 commit提交事务时,如何将 redo log buffer 中的日志刷新到 redo log file 的3种策略。

  • innodb_flush_log_at_trx_commit=1

  • 每次事务提交时都将进行同步, 执行主动刷盘操作,如上图的红线位置,所以只要事务提交成功,redo log记录就一定在硬盘里,不会有田可数据丢失。
  • 该种方式是MySQL innoDB存储引擎默认的刷盘机制。
  • 如果事务执行期间MySQL挂了或宕机,这部分日志丢了,但是事务并没有提交,所以日志丢了也不会有损

失。可以保证ACID的D,数据绝对不会丢失,但是效率最差的。

  • innodb_flush_log_at_trx_commit=2

  • 为2时,只要事务提交成功,redo log buffer中的内容只写入文件系统缓存(pagecache
  • 如果仅仅只是MySQL挂了不会有任何数据丢失,但是操作系统宕机可能会有1秒数据的丢失,这种情况下无法满足ACID中的D
  • 数值2的效率是高于数值等于1的
  • innodb_flush_log_at_trx_commit=0

  • 为0时,后台线程每隔1秒进行一次重做日志的刷盘操作,因此MySQL挂了最多丢失1秒钟内的事务。
  • 这种方式效率是最高的,这种策略也有丢失数据的风险,也无法保证持久性。
  • 其他被动触发刷盘的场景

除了上面3种策略进行刷盘以外,还有两种场景会让一个没有提交的事务的 redo log 写入到磁盘中。

  • redo log buffer 占用的空间即将达到 innodb_log_buffer_size 一半的时候,后台线程会主动写盘。注意,由于这个事务并没有提交,所以这个写盘动作只是 write,而没有调用 fsync,也就是只留在了文件系统的 page cache
  • 并行的事务提交的时候,顺带将这个事务的 redo log buffer 持久化到磁盘。假设一个事务 A 执行到一半,已经写了一些 redo logbuffer 中,这时候有另外一个线程的事务 B 提交,如果 innodb_flush_log_at_trx_commit 设置的是 1,那么按照这个参数的逻辑,事务 B 要把 redo log buffer 里的日志全部持久化到磁盘。这时候,就会带上事务 A 在 redo log buffer 里的日志一起持久化到磁盘。

小结:

我们可以根据实际的业务场景,在性能和持久性做一些权衡,但建议使用默认值,虽然操作系统宕机的概率理论小于数据库宕机的概率,但是一般既然使用了事务,那么数据的安全相对来说更重要些。

redo log写入数据页机制

目前事务日志已经落入到磁盘的redo log file中了,MySQL会去读取这个文件将数据写入到数据页中。

很显然,目前对redo log file会进行读和写的操作。在日志文件组中有两个重要的“指针”,分别是 write pos、``checkpoint

  • write pos是当前记录的位置,一边写一边后移
  • checkpoint是当前要擦除的位置,也是往后推移

  • 每次刷盘 redo log 记录到日志文件组中,write pos 位置就会后移更新。
  • 每次MySQL加载日志文件组恢复数据时,会清空加载过的 redo log 记录,并把checkpoint后移更新。
  • 如果write pos 追上 checkpoint ,表示日志文件组满了,这时候不能再写入新的 redo log记录,MySQL 得停下来,清空一些记录,把 checkpoint 推进一下,如下图:

这就是整个redo log file中的日志恢复到数据页中的过程。

总结

本文讲解了事务日志redo log在MySQL innoDB存储引擎工作的机制,它主要是用来保证事务的持久性,避免数据丢失。如果本文对你有帮助,请留下一个赞。

到此这篇关于详解MySQL事务日志redo log的文章就介绍到这了,更多相关MySQL事务日志redo log内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql多表join时候update更新数据的方法

    mysql多表join时候update更新数据的方法

    如果item表的name字段为''就用resource_library 表的resource_name字段前面加上字符串Review更新它,他们的关联关系在表resource_review_link中。
    2011-03-03
  • MySQL实现乐观锁的方式详解

    MySQL实现乐观锁的方式详解

    在 MySQL 中,可以通过使用乐观锁来实现并发控制,以避免数据冲突和并发更新问题,乐观锁是一种乐观的思想,它假设并发操作不会导致冲突,只有在提交更新时才会检查是否发生冲突,本文给大家介绍了Mysql如何实现乐观锁,需要的朋友可以参考下
    2023-09-09
  • windows系统mysql压缩包版本安装过程

    windows系统mysql压缩包版本安装过程

    这篇文章主要介绍了windows系统mysql压缩包版本安装过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • clickhouse中Nullable与非空字段的建表与类型互转方式

    clickhouse中Nullable与非空字段的建表与类型互转方式

    这篇文章主要介绍了clickhouse中Nullable与非空字段的建表与类型互转方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • SQL JOIN 子句合并多个表中相关行全面指南

    SQL JOIN 子句合并多个表中相关行全面指南

    这篇文章主要为大家介绍了SQL JOIN 子句合并多个表中相关行全面指南,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • MySQL学习之MySQL基本架构与锁

    MySQL学习之MySQL基本架构与锁

    这篇文章主要介绍了MySQL的基本架构和锁,锁的分类有两种有按粒度分,按功能,也有不同的类型,感兴趣的小伙伴可以参考阅读
    2023-03-03
  • mysql中insert into的基本用法和一些示例

    mysql中insert into的基本用法和一些示例

    INSERT INTO用于向MySQL表插入新行,支持单行/多行及部分列插入,下面给大家介绍mysql中insert into的基本用法和一些示例,感兴趣的朋友一起看看吧
    2025-06-06
  • mysql数据库迁移至Oracle数据库

    mysql数据库迁移至Oracle数据库

    这篇文章主要为大家详细介绍了mysql数据库迁移至Oracle数据库的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • MySQL中关于null值的一个小问题

    MySQL中关于null值的一个小问题

    这篇文章主要介绍了MySQL中关于null值的一个小问题,帮助大家更好的理解和学习使用MySQL,感兴趣的朋友可以了解下
    2021-03-03
  • mysql事件的开启和调用

    mysql事件的开启和调用

    这篇文章主要介绍了mysql事件的开启和调用,需要的朋友可以参考下
    2015-01-01

最新评论