MySQL的日志 - redo log
nanshan 2024-12-02 23:29 9 浏览 0 评论
关注我《程序猿集锦》,获取更多分享。
- 前言
- 什么是redolog
- relaylog的作用
- 物理日志VS逻辑日志
- redolog的组成
- redolog的两阶段提交
- reldolog日志的刷盘
- redolog对事务的支持
- redolog和binlog的区别
- redolog其他的几个参数
- 最后
前言
前面的文章中,我们依次介绍了MySQL的slow query log、binlog、relaylog,如果对这三种log仍然有疑问的话,可以向前翻一翻文章查看。今天我们来聊一聊MySQL中的另外一个重要的日志,它就是redolog。
什么是redolog
redolog,我们经常翻译为重做日志。
redolog是InnoDB存储引擎所特有的一种日志,其他存储引擎没有这个日志功能,例如像之前我们用过的MyISAM存储引擎就没有这种redolog的功能。我们知道MySQL从宏观上看,可以分为两次:server服务层和store engine存储引擎层。而我们的redolog就是属于存储引擎层特有的日志。像binlog、relaylog他们是属于服务层日志,所有的存储引擎都会生成这种日志,并且这种日志是先于redolog之前写的,写成功binlog之后才会写redolog。
relaylog的作用
redolog是用来做崩溃恢复使用的,这种崩溃恢复不需要我们人为的参与,MySQL自己内部自己实现了这种崩溃恢复的功能,我们只管享受这种功能给我们带来的服务即可,这种服务给我们的感受就是:MySQL数据库异常宕机的时候,重启服务之后,数据库中之前提交的记录都不会丢失数据仍然可以正常恢复,不管这种提交的记录是否已经更到具体的表所对应的磁盘page也中。
那么MySQL内部在实现崩溃恢复的功能时,到底是如何实现的呢? 举例来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到redo log里面(redolog日志是循环追加写的,属于顺序IO,记录的速度在某些程度上可以和内存相媲美),并更新内存,这个时候更新就算完成了。MySQL在崩溃恢复的时候,会从记下来的redolog中找到已经提交的更改内容,所以不会担心MySQL异常重启后,数据的丢失。
InnoDB 引擎会在适当的时候,将这redolog中记录的操作更新到表中数据对应的page页所在的物理磁盘上,而这个更新往往是在MySQL服务比较空闲的时候去刷新到磁盘,此时才是真正的把更新的数据内容刷新到对应的page页中。而这个更新redolog日志中的内容到真正的表数据对应的page页的刷盘操作通常比费时的,需要从磁盘中找到对应的page页,还涉及到分页或合并的各种操作,属于随机IO写入性能太差,所以MySQL没有在执行更新操作的时候,并没有直接去更新真正的数据页中的内容,而只是更新了缓存和记录的redolog日志。先写日志,再写磁盘,这就是很多软件在提高写的性能的时候所使用的WAL(write ahead logging)预写日志的功能。
MySQL的这种崩溃恢复的功能,这就是我们经常所说的crash-safe,而实现这个crash-safe功能的主要组件就是redolog。因为只有innodb存储引擎才有这个特有的日志,所有只有innodb才支持这种崩溃恢复数据不丢失的特性,这也是为什么innodb存储引擎替代myiasm存储引擎成为主流默认的存储引擎的原因之一。
在最早的时候MySQL里并没有InnoDB引擎。MySQL自带的引擎是MyISAM,但是MyISAM没有crash-safe的能力,binlog日志只能用于归档。而InnoDB是另一个公司以插件形式引入MySQL的,既然只依靠binlog是没有crash-safe能力的,所以InnoDB使用另外一套日志系统,也就是redo log来实现crash-safe能力。这就是为什么会有relaylog日志产生的原因。
物理日志VS逻辑日志
redolog从另外一个维度上来讲,它属于一种物理日志。
那么什么是物理日志呢?物理日志记录的是每一个page页中具体存储的值是多少,在这个数据页上做了什么修改。与物理日志对应的是逻辑日志,逻辑日志是记录的每一个page页面中具体数据是怎么变动的,它会记录一个变动的过程,比如把ID=3的行的age字段改为``30。像undolog、binlog、relaylog`这些日志,它们就属于逻辑日志,记录的是数据变化的一个过程、或SQL语句的逻辑。这样可能比较抽象,不容易理解,我们下面举例说明一下。
例如我们把一个page页总的一个数据从1改为2,再从2改为3,再从3改为4,再从4改为5。这是这个数据在page页中变换的过程。在物理日志中,它只会记录最后的一个值5,表示这个page页中的数据的值为5。而逻辑日志会记录1->2,2->3,3->4,4->5这个数据变化的过程。
redolog的组成
只要是使用的innodb存储引擎,那么redolog就一定是存在的。它们在磁盘上会落实成固定个数固定大小的日志文件。一般有2个或4个,这可以在初始化MySQL实例的时候,可以进行配置。如下是我自己的一个MySQL实例的redolog配置,配置了2个redolog日志文件:
root@test:/var/lib/mysql# pwd
/var/lib/mysql
root@test:/var/lib/mysql# ls -lstr ib_logfile*
49152 -rw-r----- 1 mysql mysql 50331648 Dec 28 15:45 ib_logfile1
49152 -rw-r----- 1 mysql mysql 50331648 Jan 3 12:53 ib_logfile0
root@test:/var/lib/mysql# du -sh ib_logfile*
48M ib_logfile0
48M ib_logfile1
root@test:/var/lib/mysql#
决定redolog日志文件的个数的参数是innodb_log_files_in_group,日志文件的个数建议设置为3或4。决定每一个日志文件大小的值为innodb_log_file_size,单个日志文件最大值建议设置为1GB,如下是查看我自己的一个MySQL示例的redolog的参数配置信息:
mysql> show variables like 'innodb_log_files_in_group';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| innodb_log_files_in_group | 2 |
+---------------------------+-------+
1 row in set (0.00 sec)
mysql> show variables like 'innodb_log_file_size';
+----------------------+----------+
| Variable_name | Value |
+----------------------+----------+
| innodb_log_file_size | 50331648 |
+----------------------+----------+
1 row in set (0.00 sec)
mysql> select 50331648/1024/1024;
+--------------------+
| 50331648/1024/1024 |
+--------------------+
| 48.00000000 |
+--------------------+
1 row in set (0.00 sec)
注意:如果要修改这个参数的值,需要停止MySQL服务才可以。一般在初始化完成之后,不建议修改这个值的大小。
redo log是循环写的,空间固定会用完。它一般是由2个或4个日志文件组成,当写完1个后,会写第2个,当第2个页写完后,会再去写第1个,如此往复循环,当然在写覆盖写第1个文件之前,需要把里面的日志内容,刷新到磁盘,然后再去覆盖写。binlog是可以追加写入的。"追加写"是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
redolog循环写的方式向下面这个图片所示,write pos 到 check point 之间的部分是 redo log 空着的部分,用于记录新的记录;check point 到 write pos 之间是 redo log 待刷盘的数据页更改记录。当 write pos追上check point 时,会先推动 check point 向前移动,空出位置再记录新的日志。启动 innodb 的时候,不管上次是正常关闭还是异常关闭,总是会进行恢复操作。因为 redo log记录的是数据页的物理变化,因此恢复的时候速度比逻辑日志(如 binlog )要快很多。
redolog的两阶段提交
什么是redolog的两阶段提交呢?就是在写redolog日志的时候,并不是直接把redolog标记为完成状态。而是中间会有一个prepare状态。为了更好理解这个概念,这里我们参考下面这个SQL语句执行流程图来分析一些这个两阶段提交的含义。
从图中,我们可以看出,一条更新语句的大致执行流程是这样的:
- server服务层的执行器,调用存储引擎层的API接口,去查询数据。
- innodb存储引擎层查询buffer pool缓存中的数据。
- 如果查询缓存中包含待查询的数据,则直接返回给server服务层的执行器。
- 如果缓存中没有结果则从磁盘中去读取数据,读取数据后,再返回给server服务层,同时把查询到的数据更新到buffer pool中的数据内容。
- server层的执行器收到查询后的数据后,执行更新操作。
- server层调用innodb存储引擎层的API接口更新数据。
- innodb存储引擎层更新数据到change buffer缓存池中。
- innddb存储引擎层记录redolog,并把其状态设置为prepare状态。
- innodb存储引擎层通知server的执行器,change buffer已经更新,redolog已经进入prepare待提交的就绪状态,可以记录binlog日志的。
- server层的执行器记录binlog到binlog的缓冲池中。(这里缓冲池中的日志何时刷盘就是通过参数sync_binlog来控制的,下面会详细介绍。)
- server层的执行器在记录完binlog之后,通知innodb存储引擎层,binlog已经记录完成。
- innodb存储引擎层收到server记录完binlog的通知后,更新redolog buffer中的redolog为commit状态。(此时redolog buffer中的日志何时刷盘就是通过参数innodb_flush_log_at_trx_commit来控制的,下面会详细介绍。)
至此,整个更新语句才真正的执行完成。通过上面的过程可以看出,在记录redolog的时候,有两个过程一个是记录redolog日志,把它的状态标记为prepare待提交状态,然后等待server层的binlog日志记录完成后,才会把redolog的日志更新为commit状态。这个过程就是redolog的两阶段提交操作。我们把上面的图简化为如下的一个图,你更能看明白:
思考问题:为什么redolog要两阶段提交?
redolog的两阶段提交是实现innodb存储引擎crash-safe功能核心。它的重要性,我们可以使用反正法来解读。试想一下:如果redolog在记录的时候不是两阶段提交。那么会有什么样的后果呢?只能有以下2种情况:
- 先写redolog,在写binlog:在一个更新操作的提交后,如果在redolog写成功之后,还没有来得及写binlog,此时发生了异常重启。由于redolog已经记录成功,所以在异常重启之后,MySQL可以根据redolog中的内容恢复到异常重启之前数据更新后的结果,但是由于binlog没有记录这个更新操作。如果日后你拿着这个binlog还原一个新库的时候,被还原的数据库中的数据就不会有这个更新操作。此时的新库和原库数据是不一致的。
- 先写binlog,在写redolog:在一个更新操作的提交后,如果在记录完成binlog之后,还没有来记得写redolog,此时发生了异常重启。由于binlog已经记录了修改操作,所以日后在使用这个binlog还原新库的时候,被还原的库中会包含这个更新操作,但是由于redolog没有被记录,数据库在异常重启后,并不能恢复到这个更新操作之后的数据内容。此时被还原的新库和原库中的数据也是不一致的。
综上两点可以看出,不管我们先记录哪个日志,都不能够做到数据的一致性。所以,innodb存储引擎在实现的崩溃恢复crash-safe功能的时候,就巧妙的使用了这样一个所谓的两阶段提交的方式来保证数据和日志的一致性。
你可能会有这样的疑问:在redolog两阶段提交的前提下,如果在redolog记录为prepare状态之后,binlog记录完成之后,redolog还没有来得及改为commit状态的时候,也就是上面图中②和③都执行完了,但是④没有执行,此时MySQL异常重启了,会怎么样?针对这种情况,MySQL在异常重启做恢复的时候,会去比较redolog中的内容和binlog中的内容。如果发现像上面这种情况,也会认为是成功的,因为binlog已经记录,只是差redolog中的一个commit状态没有修改成功。此时在后恢复的时候,也会从redolog中恢复出来这个数据的。这样binlog中有这个修改记录,崩溃恢复后的库中也从redolog中恢复了这个修改记录。以后用binlog还原的库和原库是一致的。从业务上看,就是虽然MySQL异常重启了,但是,我们的提交成功了。
也许你又有新的疑问:在redolog两阶段提交的前提下,如果是redolog记录并且标记为prepare状态了,后续binlog没有记录,也没有修改redolog为commit状态,也就是上面图中的②执行成功了,③和④都没有成功,此时MySQL异常重启了,会怎么样?这个时候,MySQL在重启恢复的时候,也是会比较redolog和binlog中的内容,发现只有redolog的prepare状态的日志,而binlog中没有日志。此时会把这条记录视为无效的redolog日志,也就不会恢复这样的一条修改记录。从业务上看,就是MySQL的异常重启,导致了我们的提交没有成功,我们只要重新提交一次就可以了,但是这并不会影响数据的一致性。
reldolog日志的刷盘
我们知道,在很多软件设计的时候,为了提高写数据的效率,并不是直接把数据写到磁盘上,而是先写在一个缓存池buffer中。然后从buffer中再刷新到磁盘上。relaylog在写的时候也是采用类似的方式,它有一个叫做redolog buffer的缓冲池,用于存储数据,然后再从这个缓冲池中刷新数据到磁盘中。具体什么时候把数据刷新到磁盘,是有参数innodb_flush_log_at_trx_commit来控制的,该参数的默认值为1,表示每个事务在提交之后,都会立即把这个事务的redolog持久化到磁盘上的ib_logfile文件中。
参数innodb_flush_log_at_trx_commit的取值范围[0,1,2]。而每一个值所代表的刷盘的方式是不一样的,具体如下:
- innodb_flush_log_at_trx_commit=0:表示每秒钟都会把redolog写入到buffer中,然后接着会调用fsync()方法,把数据持久化到磁盘上。但是考虑到在一秒内提交的事务可能不止一个,对于一个繁忙的业务系统来说,一秒钟几十个上百个事务也是很正常的。所以如果以每秒为单位去刷新redolog到磁盘,可能会丢失一秒内已提交但是未持久化到磁盘的事务的数据。
- innodb_flush_log_at_trx_commit=1:表示每个事务提交之后就会把它的redolog写入到buffer中,然后调用fsync()方法,把事务所对应的数据持久化到磁盘上。这样可以保证在MySQL异常重启后,我们提交的事务数据不会丢失。建议这个参数的值设置为1。
- innodb_flush_log_at_trx_commit=2:表示每个事务提交之后就会把它的redolog写入到buffer中,但是不是马上就持久化该事务的redolog到磁盘上,而是每秒调用一次fsync()方法,从buffer向磁盘持久化数据到磁盘上。这样对于那些已经提交且写入到buffer中,但是还没有持久化到磁盘的事务的数据可能会丢失。
注意:对于上面提到的参数innodb_flush_log_at_trx_commit设置为0或者2的时候,每秒钟调用一次fsync()方法,从buffer中持久化数据到磁盘的操作,并不是100%的保证每一秒就会持久化一次。有可能大于一秒钟,也有可能一秒钟持久化多次。当有一些DDL操作或者innodb内部的一些活动的时候,此时并不会因为innodb_flush_log_at_trx_commit的值为0或者1,就按照参数设置的方式去持久化数据到磁盘,这时候可能导致一秒钟持久化了多次数据到磁盘。Anyway,在参数innodb_flush_log_at_trx_commit不是1的情况下,是有丢失数据的风险的。
更为详细的信息,请参考MySQL的官方文档:innodb_flush_log_at_trx_commit
提到innodb_flush_log_at_trx_commit,就不得不提一句sync_binlog这个参数。其实这个参数控制着binlog日志刷新到磁盘的方式,它和innodb_flush_log_at_trx_commit参数控制着redolog刷新到磁盘的方式差不多。上面提到建议将innodb_flush_log_at_trx_commit设置为1,同理,对于sync_binlog也建议设置为1,这样就可以避免MySQL数据库在异常重启之后数据丢失的问题发生。这也是大家经常所说的双1设置的来源。
redolog对事务的支持
事物的四大特性之一:持久性 ,在MySQL的innodb存储引擎底层来说就是靠redolog来实现的。具体来说就是只要事务提交成功,那么对数据库做的修改就被永久保存下来了,不可能因为任何原因再回到原来的状态,通过前面的介绍,我们可以知道在崩溃恢复的时候,对已经提交成功事物,就是从redolog日志文件中恢复的。所以redolog是支持事务的innodb存储引擎实现事务的持久性的方式。
redolog和binlog的区别
redolog和binlog这两个日志经常被拿出来对比,我们简单列出以下他们之间的区别和联系。
对比维度redologbinlog文件的大小文件大小是固定的。文件大小是固定的,但是并不是严格等于定义的大小。文件的数目文件数目是固定的。文件数目不固定,达到单个文件的最大值之后会切分为一个新的日志文件。写的方式追加写,顺序I/O,循环覆盖写。追加写,顺序I/O。日志类型物理日志,记录的是物理页面上的具体的值。逻辑日志,记录的是SQL语句的逻辑。实现方式innodb存储引擎层特有的日志,并不是所有的存储引擎都有。server层日志,所有引擎都会生成这种日志。使用场景适用于数据库崩溃恢复,支持crash-safe的根源所在。适用于主从同步,数据恢复。
redolog其他的几个参数
redolog还有以下几个参数,这里简单介绍一下。
- innodb_log_group_home_dir:表示我们的redolog日志文件存放在磁盘的哪个目录下。一般情况下是改值为./,表示放在当前数据目录下,即datadir参数所指向的目录。
- innodb_log_buffer_size:写redolog日志文件的时候使用的缓冲池的大小。默认为16MB。一个大的日志缓冲区允许大量的事务在提交之前不写日志到磁盘。因此,如果你有很多事务的更新,插入或删除很操作,通过这个参数会大量的节省了磁盘I / O。
最后
关于redolog的分析就先到这里了,如果你有什么疑问可以给我留言。我看到会及时回复你。后续我会再分析MySQL中的其他日志,敬请期待。
相关推荐
- 今晚拿下PHP反序列化的一系列操作
-
引言在CTF中反序列化类型的题目还是比较常见的,之前有学习过简单的反序列化,以及简单pop链的构造。这次学习内容为php内置的原生类的反序列化以及一点进阶知识。在题目给的的代码中找不到可利用的类时,这...
- Win10安装Apache和PHP(apache安装php模块)
-
说明:虽然PHPStudy之类的软件给我们提供了方便的集成环境,但是其使用的是非线程安全的PHP版本(NotThreadSafe,NTS),某些功能不可以使用。所以,我们还需要自己再安装一个Apa...
- 腾讯云云函数部署laravel项目(腾讯云函数 selenium)
-
1、购买函数套餐包在Serverless控制台,选择函数套餐包进行购买2、新建函数服务2.1、模板创建选择函数URL:新建函数URL,启用公网访问:2.1.1、postman访问首页2.1.2、pos...
- 站长教你搭建属于自己的网站(站长教你搭建属于自己的网站是什么)
-
每个人都希望可以有自己的网站,因为那样高端大气上档次,低调奢华有内涵,尤其是公司用户,一般会有自己的网站。而个人呢,也可以搭建自己的网站博客,论坛等,但是一般个人都是搭建博客的。好了,那么下面站长教你...
- 微信公众号开发出现 cURL error 60: SSL certificate problem ssl证书
-
在phpstudy的环境下如果出现这样的报错cURLerror60:SSLcertificateproblem:unabletogetlocalissuercertificat...
- 【网络安全】关于PHP Study nginx解析高危漏洞的预警通报
-
网络安全近日,山石网科安全研究院监测发现PHPStudyWindows最新版本存在nginx解析漏洞,可以造成任意代码执行。一、漏洞情况phpStudy是一个PHP调试环境的程序集成包,该程序包集成...
- PHP 环境 搭建教程(php环境搭建教程linux)
-
PHP是一种编程语言,很多网站都用PHP语言编写,我们有时候需要测试一个网站,就需要PHP环境才能运行,又要安装Apache、又要安装MySQL……真的非常麻烦。其实我们可以使用PHP集成...
- 黑客搭建钓鱼平台,手把手教你如何钓鱼?
-
跨站脚本攻击XSS:通过HTML注入篡改了网页,插入了恶意的脚本,从而用户浏览网页时,控制用户浏览器的一种攻击那么,我们搭建一个XSS钓鱼平台吧,注意:这个平台仅用于学习和测试,小伙伴们不要动有坏心思...
- php源码网站搭建方法和过程(php网站源码完整)
-
web网站是我们上网的窗口,而网站是如何搭建的呢?今天我们来做一个介绍,以php代码为例来进行介绍(后续会介绍一下java代码搭建,如果想要我这里涉及的工具或源码请私信我)。1、首先你需要去网上下载你...
- 使用VS Code调试PhpStudy环境里的代码
-
最近几个月把所有项目都迁过来VSCode了(除了因为Unity调试问题反而用回了VisualStudio),PHP也就抛弃了最强的PhpStorm。这段时间抽空在帮朋友处理PHP项目,然...
- phpstudy搭建PHP+Mysql服务(用phpstudy搭建服务器)
-
PHP是一种创建动态交互性站点的强有力的服务器端脚本语言。PHP是免费的,并且使用非常广泛。同时,对于像微软ASP这样的竞争者来说,PHP无疑是另一种高效率的选项。(1)PHP环境搭建使用V...
- Windows安装phpstudy(Windows安装mysql)
-
说明:phpstudy是一个PHP+MySQL+Apache的集成环境,可以减少单独部署各个所需软件的麻烦,以及更加方便地切换版本。phpenv、wamp等软件的作用一样。由于环境的不同,安装过程中可...
- phpstudy安装及简单使用教程(phpstudy安装教程详解)
-
phpstudy前不久爆出有后门,我的看法是,去看下是哪个版本有后门,为啥会有后门,怎么解决掉这个后门,而不是听到后门就弃用了。毕竟phpstudy绿色安装,配置简单,多版本融合,真香。前言:关于开发...
- 如何对dedeCMS的开源程序进行二次开发
-
二次开发,简单的说就是在现有的软件上进行定制修改,功能的扩展,然后达到自己想要的功能和效果,一般来说都不会改变原有系统的内核。为了让更多人了解二次开发,并更方便的了解DedeCMS的二次开发,下面将会...
- mysql基础问题三问(底层逻辑;正在执行;日志观察)
-
背景:经常面试会遇到且实际工作中也会应用到的三个场景:目录:一.mysql查询时的底层原理是什么?二.如何查看正在执行的mysql语句?三.如何观察mysql运行过程中的日志信息?-----...
你 发表评论:
欢迎- 一周热门
-
-
极空间如何无损移机,新Z4 Pro又有哪些升级?极空间Z4 Pro深度体验
-
如何在安装前及安装后修改黑群晖的Mac地址和Sn系列号
-
爱折腾的特斯拉车主必看!手把手教你TESLAMATE的备份和恢复
-
10个免费文件中转服务站,分享文件简单方便,你知道几个?
-
日本海上自卫队的军衔制度(日本海上自卫队的军衔制度是什么)
-
[常用工具] OpenCV_contrib库在windows下编译使用指南
-
UOS服务器操作系统防火墙设置(uos20关闭防火墙)
-
【系统配置】信创终端挂载NAS共享全攻略:一步到位!
-
Ubuntu系统Daphne + Nginx + supervisor部署Django项目
-
WindowsServer2022|配置NTP服务器的命令
-
- 最近发表
-
- 今晚拿下PHP反序列化的一系列操作
- Win10安装Apache和PHP(apache安装php模块)
- 腾讯云云函数部署laravel项目(腾讯云函数 selenium)
- 站长教你搭建属于自己的网站(站长教你搭建属于自己的网站是什么)
- 微信公众号开发出现 cURL error 60: SSL certificate problem ssl证书
- 【网络安全】关于PHP Study nginx解析高危漏洞的预警通报
- PHP 环境 搭建教程(php环境搭建教程linux)
- 黑客搭建钓鱼平台,手把手教你如何钓鱼?
- php源码网站搭建方法和过程(php网站源码完整)
- 使用VS Code调试PhpStudy环境里的代码
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)