凭什么让日志先写?

在生活中,你一定有过类似这样的经历:

比如部门发礼品、或者说学校发课本。如果在发放的时候,大家一窝蜂的涌了过来,毕竟双拳双敌四手,渐渐你就招架不过来。

为了工作更好做,你会有几个选择,提前打印个名单,一个个来领,领的人在名单上打勾,东西拿走。或者大家都来拿,你看一眼,记在脑海里,但可能中途打个岔就记错了。也可以记住是谁,找个纸记下来,每次记一下或者隔一会记几下。

对比上面的场景,你没有发现,不同的方式,效率上也存在的差别。比如在名单上找到打勾,那就会完全串行,每个人来都得在定位到自己那条信息上,找的过程费时间。

找一张纸,每隔一段时间记一次,这样效率也还挺高,问题就在于别人打岔的频率。

在计算机科学领域也存在这样的时候,比如我们常用的数据库系统里。数据库为了不喝娃哈哈AD钙奶,就能保证ACID中的A和D,使用了一种被称做「WAL」的机制。全称是write-ahead logging。数据库中所有的变更,会先写到日志里,最后才会写到持久存储的数据文件中。像MySQL 里的 redo log 和undo log 就是这种机制。

像你在纸上记录一样,一直不停的向后写,顺序写,速度就会快,时不时的回过头去检查一下,改一下速度就降下来了。

如果大量记录到白纸上的内容,没有及时的汇总记录到一个表格上,那等最后全部汇总也比较费力气。就像数据库里一直写WAL之后就应用到内存数据修改,速度很快,但如果出现故障的时候,就需要重新回放大量的redo log,恢复时间也无法接受。

就像行政急着要结果的时候,你才开始「回放」白纸上的内容,就会慢很多。如果是在发放的过程中,可以过一段时间汇总一下,然后在白纸上加个「标记」,用于一会提示自己上次算到什么位置了。这种就是数据库里的 checkpoint,下次恢复的时候,就直接从checkpoint 开始向后恢复就行,前面的已经持久化到了磁盘,不用再费事了。

此外,计算机里,许多时候,都是一个根据自己的场景权衡的过程。比如对于使用WAL的时候,MySQL 提供了不同的配置来支持什么时机,多长时间将 log 应用到数据文件,毕竟log 写到磁盘也还是要花点儿时间的。每次都刷盘,会影响效率,但间隔时间太长,就会在机器故障的时候丢失数据。

MySQL 默认将log 刷到磁盘的时机有三个:

  • 提交一个事务的时候

  • 固定大小的  log buffer 满了的时候

  • 无论 log buffer 是否满,每秒会刷一次

redo log 写磁盘的过程

redo log buffer和page cache都是在内存中,所以写入这两者都比较快,而fsync则需要消耗磁盘IO。Mysql的后台每隔1秒也会自动将redo log buffer中的内容刷到磁盘中去。

借用MySQL 官方博客的几张图来说明下

那有了redo log,就保证了故障时安全了吗?是的。

机器在故障的时候,内存中包含数据的内容,也就是所谓的「脏页」一般就会丢了,怎么样恢复丢失的数据呢?咱们前面看到,redo log 先刷盘,之后真正的数据库变更才刷盘,所以我们丢失的数据已经保存在磁盘中的redo log里了。重放redolog 就可以。但这里有例外的情况是MySQL 里包含一个   innodb_flush_log_at_trx_commit 的配置,默认是1,即严格的D,非1的情况下会丢失redo log buffer和page cache中的数据。


上次送书,除了留言点赞获奖的读者外,分别根据助手APP里提示【分享最多】和【阅读最多】各取第一名,对于和留言获奖者重复的,顺延一位。

请【无心看剧】和【陈良良】两位读者看到后后台联系我,提供快递收货信息。

相关阅读

MySQL: 喂,别走,听我解释一下好吗?

Java七武器系列长生剑 -- Java虚拟机的显微镜 Serviceability Agent

Java七武器系列霸王枪 -- 线程状态分析 jstack

Java七武器系列孔雀翎-- 问题诊断神器BTrace

嵌套事务、挂起事务,Spring 是怎样给事务又实现传播特性的?

怎样阅读源代码?

源码|实战|成长|职场

这里是「Tomcat那些事儿」

请留下你的足迹

我们一起「终身成长」

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值