Vastbase G100核心技术介绍之【增量检查点】

2022-02-18 00:00:00 增量 队列 磁盘 日志 检查点

数据库系统发生故障时,需要检查WAL日志决定哪些事务需要重做、哪些需要撤销,理论上需要遍历所有日志确定该信息。为了避免性能低下的日志遍历,通过引入全量检查点技术,从上一个检查点位置开始搜索而无需搜索所有日志,但全量检查点带来的问题是把所有的脏页进行刷盘,导致系统性能出现抖动。增量检查点作为Vastbase G100的核心技术,可避免全量脏页刷盘引起的性能抖动,实现系统持续平稳运行。



全量检查点


当数据库系统发生故障时,我们必须检查事务日志,决定哪些事务需要重做,哪些需要撤销。原则上,我们需要搜索整个日志来确定该信息,但这样做有两个主要的困难:


  • 如果事务日志很大,这个过程耗时太长;

  • 大多数需要重做的事务已把其更新写入数据文件,尽管对它们重做不会造成不良后果,但会使恢复过程变得更长。


为了解决这种开销,引入了检查点机制。简单检查点的主要执行过程如下:


  • 将当前位于内存中的事务日志持久化;

  • 将脏页持久化;

  • 记录Checkpoint日志,其中保存REDO点,即重做的起始位置。


这个过程中若数据库运行时产生的脏页太多,则将脏页持久化会非常耗时,磁盘写出现峰值,导致系统性能急剧下降。为后文描述方便,我们称这种机制为全量检查点。


增量检查点


引入检查点机制的主要目的是为了减少不必要的日志重做,进而缩短系统恢复时间,全量检查点机制保证REDO点之前的数据已经全部持久化。


不难发现,REDO点更新的越及时,需要重做的日志就越少,恢复时间也就越短,但这意味着需要频繁的执行检查点,按照全量检查点的实现机制,也就是说会频繁的出现磁盘写峰值。那有没有一种机制可以及时的更新REDO点但规避频繁出现磁盘写峰值的问题呢?


全量检查点机制的主要问题是集中刷脏导致系统性能下降,为此我们可以将脏页持久化操作分摊到整个系统的运行过程中:采用工作线程连续地在后台刷脏。每次执行检查点时记录下此刻已经持久化的数据位置,这种方式我们称之为增量检查点。


增量检查点的实现机制如下:


  • 维护一个脏页队列,队列中保存了已经持久化的事务日志的LSN(Log Sequence Number,事务日志的位置)信息recLSN,系统启动时recLSN的值为REDO点,系统运行过程中事务日志落盘会更新该值;

  • 每个脏页在放入队列中时会记录此时队列的recLSN,若脏页已经在队列中则不会再次放入,也不会更新该脏页对应的recLSN;

  • 后台工作线程扫描脏页队列,将对应的数据页持久化并将脏页移出队列;

  • 记录Checkpoint日志,若脏页队列为空取队列的recLSN作为REDO点,若队列非空则取队列头部页面的recLSN作为REDO点。



上述过程第(3)步在实际实现时可以通过将队列中的任务拆分为多个部分,每个工作线程负责一部分这种并行的方式来减少刷脏所需的时间。


通过这种小批量分阶段滚筒式进行脏页的持久化,避免了全量检查点方式集中刷脏导致磁盘瞬间IO压力太大的问题,使得系统的性能更加平稳,另外执行增量检查点的代价变得很低,可以缩短执行增量检查点的时间间隔使得REDO点的更新更加及时,减少系统恢复所需的时间。


全量检查点的必要性


数据库运行过程中的某些操作,例如CREATE DATABASE操作需要将脏页中的数据落盘的,数据库正常停止的时候显然要做一次全量检查点,也就是说有了增量检查点机制,全量检查点也是必须。


为了区分在执行检查点时是全量还是增量,在请求执行检查点时通过不同的状态标志来区分。


增量检查点带来的问题


在PostgreSQL中为了避免数据持久化时页面可能损坏(partial write)的问题,引入了Full Page Write机制:


在执行检查点后对页面的次修改会将整个页面的内容写入WAL中,这个机制虽然解决了问题,但代价是增加了WAL的大小。在增量检查点机制下,这个问题被进一步放大,因为检查点会执行的更加频繁。


WAL的增大一方面是需要更多的磁盘空间来存储,其次是增大了主备机之间需要传输的日志量,对于实际生产情况而言这种代价往往是不可接受的,我们需要寻找别的方法解决页面损坏的问题。


目前Vastbase G100的事务日志只是记录了行级别的修改信息,这些信息在故障恢复时若遇到页面损坏的问题是不足以恢复完整的页面的,考虑页面损坏可能出现的场景往往是数据库正在将脏页从内存写入磁盘时服务器掉电或者操作系统崩溃,为此我们可以先将脏页写入一个特定的文件中,待这个文件落盘后再将脏页写入堆表的数据文件。


若在写入特定文件时服务器崩溃则堆表数据文件不会损坏,若在写入堆表数据文件时服务器崩溃则特定文件中的数据是完整的可以利用其恢复堆表数据,这就是所谓的double write技术,虽然double write使得每个脏页落盘要写两次磁盘,但考虑到只有将脏页落盘时才会触发,另外我们可以通过后台工作线程持续刷脏,降低集中刷脏的可能。


测试结果对比


对比全量和增量检查的实现机制不难发现增量检查点会使得磁盘负载更加平滑,系统性能更加稳定,全量检查点则可能出现磁盘负载峰值,系统运行过程中会出现明显的性能抖动。


为了验证这一点,笔者利用BenchmarkSQL工具测试了Vastbase G100和PostgreSQL的TPC-C,结果如下:


Vastbase G100增量检查点磁盘IO


Vastbase G100增量检查点tpmC


PostgreSQL全量检查点磁盘IO


PostgreSQL全量检查点tpmC


从图中可以清晰的发现PostgreSQL的tpmC出现周期性的抖动,而Vastbase G100的tpmC则非常稳定


综上,增量检查点通过与double write技术的融合,使得磁盘负载更加平滑,系统性能更加稳定。


原文链接:https://mp.weixin.qq.com/s/i7gCnZ4zw3rTjbvevN0_yQ


相关文章