在你的生活中,你一定有过类似的经历:比如来自部门的礼物,或者来自学校的教科书。要是发的时候大家都冲过去,毕竟你两拳两敌四手,渐渐的你就招架不住了。为了做得更好,你会有几个选择,提前打印出一个清单,然后一一挑选。或者大家来拿,你看一眼,记在脑子里,但中途可能弄错了,记错了。你也可以记住是谁,找一张纸记下来,每次或每隔一段时间。对比上面的场景,你有没有发现不同的方式在效率上存在差异。例如,如果您在列表中找到一个复选标记,它将被完全序列化。每个人都必须找到自己的信息,而找到它的过程需要时间。找一张纸,每隔一段时间就记下来,效率还是挺高的。问题在于经常被别人打断。这在计算机科学领域也存在,比如在我们常用的数据库系统中。为了在不喝娃哈哈AD钙奶的情况下保证ACID中的A和D,数据库使用了一种叫做“WAL”的机制。全称是预写日志记录。数据库的所有变化都会先写入日志,最后写入数据文件进行持久化存储。MySQL中的redolog和undolog就是这样的机制。就像你在纸上记录一样,一直倒着写,顺着写,速度会快一些,时不时回去看看,改了之后速度就慢下来了。大量记录在白皮书上的内容如果没有及时总结记录成表格,等待最后的总结会比较费力。就好比在数据库里写WAL,然后应用到内存数据修改上。速度很快,但是如果发生故障,需要重放大量的redolog,恢复时间难以接受。就像行政部门急于出结果,你才开始“回放”白皮书上的内容,就会慢很多。如果是在分发的过程中,可以过段时间总结一下,然后在白纸上加个“记号”,提醒自己上次统计到哪里了。这是数据库中的检查点。下次恢复的时候直接从checkpoint往回恢复即可。之前的已经持久化到磁盘了,就不用费心了。另外,在电脑里,很多时候,是根据自己的场景权衡的过程。例如,在使用WAL时,MySQL提供了不同的配置来支持何时以及多长时间将日志应用到数据文件中。毕竟将日志写入磁盘还是需要一些时间的。每次都刷盘会影响效率,但如果间隔时间过长,机器出现故障时数据会丢失。MySQL默认刷日志到磁盘有三种时机:事务提交时,固定大小的日志缓冲区满。当日志缓冲区已满时,重做日志将每秒刷新一次。redologbuffer和pagecache都在内存中,所以写入两者更快,而fsync消耗磁盘IO。Mysql后台也会每隔1秒自动将redologbuffer的内容刷新到磁盘。借用MySQL官方博客的几张图来说明,有了redolog,失败就安全了吗?是的。当机器出现故障时,内存中包含的数据内容,即所谓的“脏页”,一般都会丢失。如何恢复丢失的数据?前面我们看到,redolog先被flush,然后才是真正的数据库磁盘发生变化后才被flush,所以我们丢失的数据已经保存在磁盘上的redolog中了。只需重播重做日志即可。但这里有一个例外。MySQL包含innodb_flush_log_at_trx_commit的配置。默认为1,即严格D。如果不为1,redologbuffer和pagecache中的数据会丢失。本文转载自微信公众号“Tomcat物语”,可关注下方二维码。转载此文请联系Tomcat那些东西公众号。
