全量与增量检查点
在上述对事务日志以及共享缓冲区的描述中,有一个关键的信息,那就是事务日志的持久化与事务提交是同步的,但事务内对页面相关修改的持久化与事务提交不是同步的;也就是说,事务提交需要与这个事务相关的 Redo日志被强制刷盘,但是并不强制要求相关的页面也被强制刷盘。当一个数据库实例故障重启后,实例在启动过程中,之前没有能够及时刷盘的改动需要使用事务日志进行恢复。但是日志回放的代价是很高的,性能也相对比较慢。为了避免每次数据库都需要从头恢复事务日志,数据库自身会定期创建检查点,用户也可以通过命令手动创建检查点。
创建检查点的过程中,存储引擎会将数据缓冲区中脏页写到磁盘中,并记录日志文件和控制文件。记录信息中的recLSN 代表着此次检查点中,在此 LSN 之前的日志对应的所有改动均已被持久化,下次的数据恢复可以直接从此 LSN 开始;同时在此LSN 之前的事务日志,在其他用途(主备实例同步、数据备份等)时,也可以被回收重新使用。
由于检查点本身需要将缓冲区内所有的脏页面刷盘(全量检查点),因此每次检查点从性能角度会对数据库实例所在物理环境引入大量的IO,磁盘的峰值往往意味着性能的波动。同时因为存在大量的IO 开销,因此检查点的打点不能过于频繁,recLSN推进较慢,那么重启数据库时也就会存在较多的 Redo日志需要回放,存在重启恢复时间过长的问题。为了解决这一问题,行存储引擎引入了增量检查点的概念。
在增量检查点机制下,会维护一个脏页面队列(dirtypagequeue)。脏页是按照LSN 递增的顺序放到队列中的,定期由一个专门刷脏页面的后台线程页面刷盘线程(pagewriter)进行定期定量的刷脏页下盘操作,脏页面队列如图22所示。
队列中维护一个recLSN,记录目前已经被刷盘的脏页对应的 LSN 大小,即在队列中脏页对应的事务提交、其相对的事务日志下盘后,此recLSN 标记会被更新。在触发增量检查点时,并不需要等待脏页刷盘,而是可以使用当前脏页队列的recLSN 作为检查点的recLSN 记录。增量检查点的存在使得整个系统中的IO 更加平滑,并且系统的故障恢复时间更短,可用性更高。
原文链接:https://blog.csdn.net/GaussDB/article/details/116012521




