2.4 CheckPoint,讲到了CheckPoint解决的问题,其中第三点是“重做日志不可用时,刷新脏页”。详细的描述是这样的:
重做日志可以被重用的部分是指这些重做日志已经不再需要,即当数据库发生宕机时,数据库恢复 *** 作不需要这部分的重做日志,因此这部分就可以被覆盖重用。若此时重做日志还需要使用,那么必须强制产生CheckPoint,将缓冲池中的页至少刷新到当前重做日志的位置。
读到这一段的时候,尤其是加粗部分的内容,我不禁产生疑惑:缓冲池中的页不是本来就和redolog状态相同吗?为什么还需要将缓冲池中的页刷新?
第二天回顾的时候,我思考了一下。(以下为是个人解读,不一定对,如有错误欢迎批评指正!)
首先,由于InnoDB采用WAL搭配redolog保证crash safe,也就是更新数据的时候,先写redolog,再写buffer pool中的数据页。又由于写redolog时需要先写redolog buffer,而这个过程由于不需要doublewrite,应该是比较快的。所以,这就可能导致在数据量大、并发写多的情况下,很多 *** 作都被写到了redolog中,但还没有写到buffer pool中的数据页中,如图:
而这时,由于redolog是循环写,在空间不足时(写不下了),就产生了书上说的“不可用”状态。
因此此时,必须强制先将buffer pool中的数据页写入一部分(刷回盘),和redolog保持一致,从而腾出空间。具体的解决措施,即是属于Fuzzy CheckPoint的Async/Sync Flush CheckPoint,根据checkpoint_age,分别和async_water_mark以及sync_water_mark比较,选择相应的Flush *** 作。具体判断过程如下:
当checkpoint_age < async_water_mark时,无需刷页当async_water_mark < checkpoint_age < sync_water_mark时,触发Async Flush当sync_water_mark < checkpoint_age时,触发Sync Flush(一般很少发生)
其中,water_mark的计算公式为:
async_water_mark = 75% * total_redo_log_file_size
sync_water_mark = 90% * total_redo_log_file_size
而checkpoint_age的计算公式为:
checkpoint_age = redo_lsn - checkpoint_lsn
LSN即Log Sequence Number,我的理解里,其实就和kafka里的offset作用差不多。
经过Flush *** 作之后,确保checkpoint_age < async_water_mark。
回到刚才的问题,所以,文中的“不可用”,指的应该是redolog写空间不足。
写在最后:
之前读书做的笔记基本都在书上或者本地的markdown上,但是对于有价值的问题,我决定还是放在博客上和大家共同讨论,毕竟更多的交流往往意味着更多的收获。
并且,这篇文章应该也是我写博客比较多的时间段的一个开始。时值寒假,空闲时间相对较多;也有之前吸取的一些经验教训,督促我在这个时间沉下心去学一些知识。
希望自己能坚持下去。
(cndn不给标题名带内幕,说我标题夸张,可是这本书名字就叫技术内幕啊 ; )
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)