MySQL 为什么需要 redo log?
文章目录
- 1. 谁的 redo log
- 2. buffer pool
- 3. change buffer
- 4. redo log 的诞生
- 4.1 redo log buffer
- 4.2 redo log 落盘
今天想和大家聊一聊 MySQL 中的 redo log,其实最早我是想聊两阶段提交的,后来想想可能有小伙伴还不了解 binlog,所以就先整了一篇 binlog:
- 手把手教你玩 MySQL 删库不跑路,直接把 MySQL 的 binlog 玩溜!
- MySQL删库不跑路(视频版)
binlog 大家懂了之后,接下来还差个 redo log,redo log 大家也懂了,那么再讲两阶段提交相信小伙伴们就很容易懂了,咱们一步一步来。
1. 谁的 redo log
学习 redo log,我觉得首先要搞明白一个问题,就是是谁的 redo log?
我们知道,MySQL 架构整体上分为两层:Server 层和存储引擎层,如下图:
前面松哥文章+视频跟大家聊的 binlog,是 MySQL 自己提供的 binlog,而 redo log 则不是 MySQL 提供的,而是存储引擎 InnoDB 自己提供的。所以在 MySQL 中就存在两类日志 binlog 和 redo log,存在两类日志既有历史原因(InnoDB 最早不是 MySQL 官方存储引擎)也有技术原因,这个咱们以后再细聊。
先把这个问题搞清楚,后面很多地方就容易懂了。
2. buffer pool
在正式介绍 redo log 之前,还有一个 buffer pool 需要大家了解。
小伙伴们知道,InnoDB 引擎存储数据的时候,是以页为单位的,每个数据页的大小默认是 16KB,我们可以通过如下命令来查看页的大小:
16384/1024=16
刚好是 16KB。
计算机在存储数据的时候,最小存储单元是扇区,一个扇区的大小是 512 字节,而文件系统(例如 XFS/EXT4)最小单元是块,一个块的大小是 4KB,也就是四个块组成一个 InnoDB 中的页。我们在 MySQL 中针对数据库的增删改查操作,都是操作数据页,说白了,就是操作磁盘。
但是大家想想,如果每一次操作都操作磁盘,那么就会产生海量的磁盘 IO 操作,如果是传统的机械硬盘,还会涉及到很多随机 IO 操作,效率低的令人发指。这严重影响了 MySQL 的性能。
为了解决这一问题,MySQL 引入了 buffer pool,也就是我们常说的缓冲池。
buffer pool 的主要作用就是缓存索引和表数据,以避免每一次操作都要进行磁盘 IO,通过 buffer pool 可以提高数据的访问速度。
通过如下命令可以查看 buffer pool 的默认大小:
134217728/1024/1024=128
默认大小是 128MB,因为松哥这里的 MySQL 是安装在 Docker 中,所以这个分配的小一些。一般来说,如果一个服务器只是运行了一个 MySQL 服务,我们可以设置 buffer pool 的大小为服务器内存大小的 75%~80%。
3. change buffer
在正式介绍 redo log 之前,还有一个 change buffer 需要大家了解。
前面我们说的 buffer pool 虽然提高了访问速度,但是增删改的效率并没有因此提升,当涉及到增删改的时候,还是需要磁盘 IO,那么效率一样低的令人发指。
为了解决这个问题,MySQL 中引入了 change buffer。change buffer 以前并不叫这个名字,以前叫 insert buffer,即只针对 insert 操作有效,现在改名叫 change buffer 了,不仅仅针对 insert 有效,对 delete 和 update 操作也是有效的,change buffer 主要是对非唯一的索引有效,如果字段是唯一性索引,那么更新的时候要去检查唯一性,依然无法避免磁盘 IO。
change buffer 就是说,当我们需要更改数据库中的数据的时候,我们把更改记录到内存中,等到将来数据被读取的时候,再将内存中的数据 merge 到 buffer pool 然后返回,此时 buffer pool 中的数据和磁盘中的数据就会有差异,有差异的数据我们称之为脏页,在满足条件的时候(redo log 写满了、内存写满了、其他空闲时候),InnoDB 会把脏页刷新回磁盘。这种方式可以有效降低写操作的磁盘 IO,提升数据库的性能。
通过如下命令我们可以查看 change buffer 的大小以及哪些操作会涉及到 change buffer:
- innodb_change_buffer_max_size:这个配置表示 change buffer 的大小占整个缓冲池的比例,默认值是
25%
,最大值是50%
。 - innodb_change_buffering:这个操作表示哪些写操作会用到 change buffer,默认的 all 表示所有写操作,我们也可以自己设置为
none
/inserts
/deletes
/changes
/purges
等。
不过 change buffer 和 buffer pool 都涉及到内存操作,数据不能持久化,那么,当存在脏页的时候,MySQL 如果突然挂了,就有可能造成数据丢失(因为内存中的数据还没写到磁盘上),但是我们在实际使用 MySQL 的时候,其实并不会有这个问题,那么问题是怎么解决的?那就得靠 redo log 了。
4. redo log 的诞生
在正式介绍 redo log 之前,还需要给大家普及一个概念:WAL。
WAL
全称是 Write-Ahead Logging
中文译作预写日志。啥意思呢?就是说 MySQL 的写操作并不是立刻更新到磁盘上,而是先记录在日志上,然后在合适的时间再更新到磁盘上,这样的好处是错开高峰期的磁盘 IO,提高 MySQL 的性能。
配合上前面的 buffer pool 和 change buffer,WAL 就是说在操作 buffer pool 和 change buffer 之前,会先把记录写到 redo log 日志中,然后再去更新 buffer pool 或者 change buffer,这样,即使系统突然崩了,将来也可以通过 redo log 恢复数据。当然,redo log 本身又分为:
- 日志缓冲(redo log buffer),该部分日志是易失性的。
- 重做日志(redo log file),这是磁盘上的日志文件,该部分日志是持久的。
那有人说,写 redo log 不就是磁盘 IO 吗?而写数据到磁盘也是磁盘 IO,既然都是磁盘 IO,那干嘛不把直接把数据写到磁盘呢?还费这事!
此言差矣。
写 redo log 跟写数据有一个很大的差异,那就是 redo log 是顺序 IO,而写数据涉及到随机 IO,写数据需要寻址,找到对应的位置,然后更新/添加/删除,而写 redo log 则是在一个固定的位置循环写入,是顺序 IO,所以速度要高于写数据。
如前文所说,redo log 涉及到两个东西:redo log buffer 和 redo log file,这两个东西我们分别来介绍。
4.1 redo log buffer
先来说 redo log buffer。
我们说数据的变化先写入 redo log 中,并不是上来就写磁盘,也是先写到内存中,即 redo log buffer,在时机成熟时,再写入磁盘,也就是 redo log file。
我们先来看看 redo log buffer 有多大:
16777216 ÷ 1024 ÷ 1024 = 16MB
可以看到,这个 redo log buffer 大小刚好是 16MB,如果你觉得这个值有点小,也可以自行修改其大小。
数据的变更都会首先记录在这块内存中。小伙伴们知道,MySQL 的增删改,如果我们没有显式的开启事务,MySQL 内部也是有一个事务存在的,当内部这个事务 commit 的时候,redo log buffer 会持久化到磁盘中。
具体来说,有如下几个持久化时机:
- innodb_flush_log_at_trx_commit
通过 innodb_flush_log_at_trx_commit 参数来控制持久化时机,该参数默认值为 1,如下图:
当然开发者可根据自己的实际需求修改该参数。该参数有三种取值,含义分别如下:
- 0:每秒一次,将 redo log buffer 中的数据刷新到磁盘中。
- 1:每次 commit 时,将 redo log buffer 中的数据刷新到磁盘中,即只要 commit 成功,磁盘上就有对应的 redo log 日志,这是最安全的情况,也是推荐使用的参数。
- 2:每次 commit 时,将 redo log buffer 中的数据刷新到操作系统缓存中,操作系统缓存中的数据每秒刷新一次,会持久化到磁盘中。
这是第一种 redo log buffer 持久化的时机。
- 当 redo log buffer 的使用量达到
innodb_log_buffer_size
的一半时,将其写入磁盘成为 redo log file。 - MySQL 关闭时,将 redo log buffer 写入磁盘成为 redo log file。
那如果 redo log buffer 中的数据还没有磁盘,MySQL 就挂了该怎么办?没写入磁盘,说明你还没 commit,既然没 commit,那就数据修改操作都还没有完成,那只能丢了就丢了,如果已经 commit 了,那么数据就会持久化到 redo log file 中,此时即使 MySQL 挂了,将来 MySQL 重启恢复了,数据也是可以被恢复的。具体的恢复逻辑,就涉及到两阶段提交了,这个松哥在后面的文章中再和大家详细介绍。
4.2 redo log 落盘
还有一个需要大家注意的问题就是 redo log 落盘,落盘的数据从哪里来?是从 redo log 日志中来还是从 buffer pool 中来?
在前面的文章中我们说过:binlog 是一种逻辑日志,他里边所记录的是一条 SQL 语句的原始逻辑,例如给某一个字段 +1,这区别于 redo log 的物理日志,物理日志记录的是在某个数据页上做了什么修改。
由于 redo log 并没有记录数据页的完整数据,所以正常的落盘其实用不到 redo log,数据落盘的时机到了时,直接拿着将脏页(buffer pool)持久化到磁盘中即可。
好啦,今天就和大家分享这么多,redo log 还有一些内容,我们在后面的文章中再继续聊~
参考资料:
- https://www.cnblogs.com/ZhuChangwu/p/14096575.html
MySQL 为什么需要 redo log?相关推荐
- Mysql中的redo log
Mysql中的redo log 1.什么是redo log redo log叫做重做日志,是保证事务持久性的重要机制.当mysql服务器意外崩溃或者宕机后,保证已经提交的事务,确定持久化到磁盘中的一种 ...
- MySQL——binlog,redo log
一.什么是binlog.redo log binlog属于逻辑日志,是逻辑操作.innodb redo属于物理日志,是物理变更.逻辑日志有个缺点是难以并行,而物理日志可以比较好的并行操作. binlo ...
- MySQL的日志 - redo log
微信搜索『coder-home』,或者扫一扫右侧的二维码,关注『程序猿集锦』. 了解更多干货分享,还有各类视频教程. 扫描它,带走我. 文章目录 前言 什么是redolog reldolog的作用 物 ...
- 说说MySQL中的Redo log Undo log都在干啥
在数据库系统中,既有存放数据的文件,也有存放日志的文件.日志在内存中也是有缓存Log buffer,也有磁盘文件log file,本文主要描述存放日志的文件. MySQL中的日志文件,有这么两类常常讨 ...
- 【图文详解】MySQL事务日志 Redo log(重做) 和 Undo log(撤销)
InnoDB Architecture https://dev.mysql.com/doc/refman/5.6/en/innodb-architecture.html 我们都知道数据库有四大属性AC ...
- Mysql 日志系统 redo log 和 binlog
日常笔记
- 必须了解的MySQL三大日志:binlog、redo log和undo log
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者: 六点半起床 juejin.im/post/68602522 ...
- 必须了解的mysql三大日志-binlog、redo log和undo log
来源:https://juejin.im/post/6860252224930070536 日志是 mysql 数据库的重要组成部分,记录着数据库运行期间各种状态信息.mysql日志主要包括错误日志. ...
- MYSQL专题-MySQL三大日志binlog、redo log和undo log
日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息.mysql日志主要包括重做日志(redo log).回滚日志(undo log).二进制日志(bin log).错误日志(err ...
- mysql redo log 数据恢复_MySQL 怎么样恢复丢失的数据?redo log 写磁盘的过程
在生活中,你一定有过类似这样的经历: 比如部门发礼品.或者说学校发课本.如果在发放的时候,大家一窝蜂的涌了过来,毕竟双拳双敌四手,渐渐你就招架不过来. 为了工作更好做,你会有几个选择,提前打印个名单, ...
最新文章
- PCL:拟合平面直线和曲线以及空间曲线的原理到算法实现
- 【iOS-Cocos2d游戏开发之十五】详解CCProgressTimer 进度条并修改cocos2d源码实现“理想”游戏进度条!...
- Winsock开发网络通信程序的经典入门
- The Class Loader Hierarchy--转载
- Acwing第 32 场周赛【完结】
- 一个div压在另一个div上面_【CSS小分享】用CSS画一个新拟态风格键盘
- leetcode - 898. 子数组按位或操作(使用了集合)
- php 输出mysql查询结果_php如何输出mysql查询结果
- cv2.error: opencv(4.4.0)_【OpenCV 4开发详解】图像连通域分析
- Jquery跨域调用(JSONP)遇到error问题的解决
- 华三的stp根桥、端口角色选举规则
- C++--第10课 - 构造与析构 - 下
- 散粉在哪个步骤用_无限回购的散粉
- 2022-2028年中国无线模组行业投资策略探讨及市场规模预测报告
- ps修改证件照的底色
- python绘制彩色地震剖面断层解释_地震剖面上的断层分析及相关意义
- Redis缓存读写策略
- 微信创建公众号,获取AppID、AppSecret以及accesstoken
- 对于Python的get-pip.py安装教程
- Linux0号进程,1号进程,2号进程
热门文章
- 人生就是个学习、思考与实践的过程
- 深入理解DirectX D3D9
- 颤抖吧,理科生们,让你们看看文科帝!
- 新冠肺炎的诊断与临床症状
- 论文进入SCI、Ei等国际检索系统的意义(转贴)
- oracle general ledger,处理 Oracle General Ledger 调整期间
- 海量固定资产如何进行盘点?
- 弘辽科技:拼多多店铺层级会掉吗?怎么划分?
- Beyond Part Models: Person Retrieval with Refined Part Pooling (and A Strong Convolutional Baseline)
- 更新应用程序安卓apk时出现解析程序包时出现问题