zl程序教程

您现在的位置是:首页 >  后端

当前栏目

谈谈传说中的redo log是什么?有啥用?

log 什么 谈谈 REDO 传说
2023-09-27 14:25:58 时间
白日梦感觉作为研发同学的你可能真的没必要了解摸清楚关于redo log的这些机制。专注于写SQL完全能hold住日常的工作。 但是呢,感觉最好还是要了解一下,因为一般面试官都知道redo log是咋回事,其次是大家茶前饭后唠嗑时也能多少能插几句嘴。

白日梦感觉作为研发同学的你可能真的没必要了解摸清楚关于redo log的这些机制。专注于写SQL完全能hold住日常的工作。


但是呢 感觉最好还是要了解一下 因为一般面试官都知道redo log是咋回事 其次是大家茶前饭后唠嗑时也能多少能插几句嘴。


一、引出 redo log 的作用#

继续我们的MySQL专题。首先回顾一下前面白日梦同你分享过的知识点。

前面我们一起学习了MySQL undo log相关的知识点 看下面这张脑图


image


磁盘上的数据文件叫表空间文件 表空间有挺多的 比如系统表空间、undo log 表空间、你也可以让create出来的每张table都有自己单独的表空间。总之MySQL会将表空间数据页通过磁盘IO加载进缓存页中。


SQL执行器会执行你发送给MySQL的SQL语句 MySQL为了提高的性能 对于增、删、改这种操作都是在内存中完成的 所谓的内存就是上图中BufferPool。比如上图中的SQL执行器执行了一条update xxx where id 1语句 然后这个id 1数据行所在的数据页就会被你修改成脏数据页。


此外MySQL还有专门的后台线程等其他机制负责将脏数据页刷新同步回磁盘。


二、思考一个问题 #

你可以结合上图然后想一下 万一脏页还没来得及刷新到磁盘中 MySQL就挂了 怎么办呢


对于业务代码来说 方才执行的事务是OK的 甚至前端都接受到了请求成功的响应。那结果修改的数据没同步回磁盘 MySQL宕机了会不会导致真实数据和逻辑上的数据不一致呢


其实不会的

MySQL使用redo log解决了这个问题 redo故名思义 重做。

当发生事务 增、删、改 时会导致缓存页变成脏页 于此同时MySQL会将事务涉及到的 对 XXX表空间中的XXX数据页XXX偏移量的地方做了XXX更新。

所以MySQL意外宕机重启也没关系。只要在重启时解析redo log中的事务然后重放一遍。将Buffer Pool中的缓存页重做成脏页。后续再在合适的时机将该脏页刷入磁盘即可。


于是对于业务方来说 everything is ok


redo log侧重于重做 redo log中记录的是物理层面的数据页、偏移量。应对的问题是 MySQL异常宕机后 如何将没来得及提交的事物数据重做出来。

而后面文章中和大家分享的bin log中记录了你对XXX表条件为XXX处的数据作了什么修改 这是些都是逻辑上的概念。


三、redo log block#

首先你得知道 redo并不是一条条直接写入磁盘中去的

在MySQL的设定中 redolog是按块 一块一块的写入到磁盘中去的。


你可以类比一下数据是按页为单位来组织的 就更容易理解为啥redo log 要按照block来组织redo。

本质上就是两个字 优化


log block长成下面这这样 分成Header、Body、Trailer三部分 总共512字节。而且是覆盖写入。


image


我粗略解读一下这幅脑图。


首先既然MySQL会写redo log 说明你的sql会对缓存页造成修改 也就意味着会走MySQL设定的事物那一套机制。既然是MySQL事物 大概率就是一组增、删、改。如果每个增、删、改都会有一个对应的redo log的话 那也就是说你的事物会产生好多redolog。这些redo会先被持续不断的写入到log block中 同一个事物产生的redo log会被标记为一个redo log group。


四、redo log buffer#

了解redo log block之后 白日梦还要跟你介绍一下 redo log buffer。

这个redo log buffer 中会划分出多个rodo log block。redo log buffer 占用一块连续的内存空间 默认大小16MB。且MySQL允许我们通过参数innodb_log_buffer_size动态的调整它。增大它的大小可以让MySQL处理大事物是不必写入磁盘。进而提升写IO性能。


引入rodo log buffer之后 就可以勾勒出这样一副脑图。


image


如图 产生的redo log 先写入redo log block。然后redo log block其实就在redo log buffer 中。


看到这里不知道你有没有想到这样一个问题 redo log buffer再怎么神奇毕竟也是仅仅在内存中 此时万一MySQL宕机了怎么办 redolog-buffer中的数据丢失了怎么办 毕竟没有写到磁盘上 MySQL重启后100%没办法将其恢复出来。

其实你并不用担心这种情况


因为在MySQL的设定中 当你要Commit事务时 redolog才会持久化进磁盘 既然你没有commit 碰巧MySQL又宕机了。那让MySQL正常重启就好了啊 反正你没有commit MySQL也也没有必要帮你恢复什么。


那 redo log buffer 何时写入磁盘呢

事物提交时把它对应的那些redo log写入到磁盘中去 这个动作可由相关参数控制 下文会说 当redo log buffer 使用量达到了参数innndb_log_buffer_size的一半时 会触发落盘。会有一个后台线程 每隔1秒就会将redo log block刷新到磁盘文件中去。MySQL关闭时也会将其落盘。


五、redo log的刷盘时机#

承接上面描述的场景 事务提交时 率先将redo log持久化进磁盘。

那你如何控制MySQL 让MySQL在Commit事务时率先将redo log持久化呢

MySQL提供了参数innodb_flush_log_at_trx_commit


该参数有几个选项 0、1、2

想要保证ACID四大特性推荐设置为1 表示当你commit时 MySQL必须将rodolog-buffer中的数据刷新进磁盘中。确保只要commit是成功的 磁盘上就得有对应的rodolog日志。这也是最安全的情况。
设置为0 每秒写一次日志并将其刷新到磁盘。
设置为2 表示当你commit时 将redolog-buffer中的数据刷新进OS Cache中 然后依托于操作系统每秒刷新一次的机制将数据同步到磁盘中 也存在丢失的风险。


六、推荐参数#始终设置 innodb_flush_log_at_trx_commit 1
如果启用了二进制日志记录 请设置 sync_binlog 1。

这也是大家常说的双1设置。前者保证redolog的不丢失、后者保证了binlog的不丢失。


关于sync_binlog参数 计划在第X、X、篇文章中分享binlog知识点的时候会再提及 欢迎关注


七、redo log group#

redo log group说的是 由N个大小相同的redo log组成一个redo log group。N的值默认为2。


你可以像下面这样查看你的MySQL的redo log group情况。

默认单个redo log文件的大小是48MB。你也可以通过上图中的innndb_log_files_size修改它。

日志文件的总大小 innodb_log_file_size* innodb_log_files_in_group 不能超过略小于512GB的最大值。

例如 一对255 GB的日志文件已达到限制 但没有超过该限制。


image


同样你可以像下面这样查看磁盘上的 redo log 文件。它们的大小和上图中的innodb_log_file_size相同。


image


innodb将log buffer中的redo log block刷新到上图中的logfile中时 以追加的方式循环写入。也就是首先在ib_logfile0的尾部追加 写满后再写ib_logfile1。当ib_logfile1写满时 情况一部分ib_logfile0接着追加写。


redo log file的大小对innodb性能影响非常大。通常来说要设置的足够大 大到可以让MySQL支持1小时线上高峰流量的接入而不切换。但是设置的过大 数据恢复的时间比较长。设置过小导致循环切换redo log file。

能聊聊 日志刷盘规则之 check point 和 LSN机制吗


参考

https://dev.mysql.com/doc/refman/5.7/en/innodb-redo-log.html

https://dev.mysql.com/doc/refman/5.7/en/replication-solutions-unexpected-replica-halt.html

https://dev.mysql.com/doc/refman/5.7/en/innodb-init-startup-configuration.html

https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit

https://dev.mysql.com/doc/refman/5.7/en/innodb-init-startup-configuration.html


推荐阅读#大家常说的基数是什么 已发布 讲讲什么是慢查 如何监控 如何排查 已发布 对NotNull字段插入Null值有啥现象 已发布 能谈谈 date、datetime、time、timestamp、year的区别吗 已发布 了解数据库的查询缓存和BufferPool吗 谈谈看 已发布 你知道数据库缓冲池中的LRU-List吗 已发布 谈谈数据库缓冲池中的Free-List 已发布 谈谈数据库缓冲池中的Flush-List 已发布 了解脏页刷回磁盘的时机吗 已发布 用十一张图讲清楚 当你CRUD时BufferPool中发生了什么 以及BufferPool的优化 已发布 听说过表空间没 什么是表空间 什么是数据表 (已发布)谈谈MySQL的 数据区、数据段、数据页、数据页究竟长什么样 了解数据页分裂吗 谈谈看 (已发布)谈谈MySQL的行记录是什么 长啥样 (已发布)了解MySQL的行溢出机制吗 (已发布)说说fsync这个系统调用吧! (已发布)简述undo log、truncate、以及undo log如何帮你回滚事物! (已发布)我劝 这位年轻人不讲MVCC 耗子尾汁 (已发布)
日志:Redo Log 和 Undo Log 本篇文章主要介绍 Redo Log 和 Undo Log: 1. 利用 Redo Log 和 Undo Log 实现本地事务的原子性、持久性 2. Redo Log 的写回策略 3. Redo Log Buffer 的刷盘时机
庖丁解InnoDB之REDO LOG 磁盘数据库为了在保证数据库的原子性(A, Atomic) 和持久性(D, Durability)的同时,还能以灵活的刷盘策略来充分利用磁盘顺序写的性能,会记录REDO和UNDO日志,即ARIES方法。本文将重点介绍REDO LOG的作用,记录的内容,组织结构,写入方式等内容,希望读者能够更全面准确的理解REDO LOG在InnoDB中的位置。本文基于MySQL 8.0代码。
你是不是 redo log 和 binlog 傻傻分不清楚? 阿粉这么贴心,肯定给你讲清楚了~ 在 MySQL 中,特别是存储引擎使用的是 InnoDB 时,那肯定绕不过去两个概念:redo log (重做日志) 和 binlog (二进制日志) 简单点儿说:redo log 是 InnoDB 存储引擎层方面的日志,所以如果你使用的存储引擎不是 InnoDB 的话,那就根本谈不上 redo log