Change Tracking Log in GreenPlum

2015-12-30

距离上次写点东西差不多有一个月了,回过头来看一下,之前写的最后一篇其实还差那么一点,一直拖着没有补上,就是关于Change tracking log的部分。上次只是简略的提了一下,其实其中的内容还是有必要总结学习一下的。

Why use CTL

上次的博客中主要描述的是resync机制,即segment mirror down掉后再起来,primary如何同步mirror不再位时产生的数据信息的。对比来看,PostgreSQL中,standby down掉后再起来,只需要从REDO的WAL最后向primary请求日志,primary只需要从此位置将后续的连续WAL日志发送给standby,standby redo后即可重新达到sync状态。然而在GreemPlum中,mirror是没有redo的,重要的事情说三遍mirror没有redo,没有redo,没有redo。primary&&mirror基于filerep做同步。所以当mirror down掉后,primary需要记录后续运行过程中产生的需要同步到mirror的信息,当mirror重新连接后,做primary resync过程中将这些信息发送给mirror即可达到一致,这个也是不得已而为之。

How does it work

Change tracking log(CTL)在GreenPlum中,总共有以下几种:meta log、full log、compact log和transient log。除去meta log,其他几种类型的log都是一样的,只是说有一些细微的差别。当mirror down掉后,master上的fts首先会通知segment primary进入CTL mode。此时primary上会启动一个子进程叫Change tracking recovery process,这个进程主要有两个功能,是什么呢?

1.FileRepPrimary_StartRecoveryInChangeTracking() -- 启动change tracking log
2.FileRepPrimary_RunChangeTrackingCompacting() -- 运行change tracking log

对于start recovery CTL而言,第一个是首先判断当前处于resync模式还是insync模式,这个是有区别的,在上一篇中介绍了resync模式的,可以看一下相关的code。insync模式下表明primary&&mirror已经同步了,此时旧的CTL信息已经没有用了,可以直接清理掉。如果当前是处于全量的resync,并且刚刚开始,此时由于全量的resync不需要依赖于CTL信息,因此直接退出。其他情况下说明需要标记CTL的信息的。第二个是扫描内存中的数据修改信息,为什么呢,因为呀,正常运行过程是在日志写盘时将信息记录到CTL中,当CTL recovery启动时,内存中含有未刷盘的日志,也就意味着可能存在未记录到CTL中的数据变化信息。此时CTL recovery需要做的事情就是将本地所有为未刷盘的日志刷盘,并且从checkpoint(Control file)往后扫描日志直到我们刚才刷新地点LSN位置,解析两者之间所有的WAL日志类型,从中提取感兴趣的日志类型,并且获取到对应修改的数据信息,将对应的数据页面的信息(s/d/r/b等,非页面内容本身)记录到CTL中,这个CTL中只记录数据的索引信息,也就能解释了前面文章中,inc resync模式下,对于普通的relation需要借助CTL中记录的信息读取页面发送到mirror了。

对于run CTL而言,其做的事情很简单即将full log经transient压缩为compact log,当然这里的压缩不是说压缩数据信息,而是一种数据整合,用到的思想就是同一个relation,同一个block,我们只需要记录最后被更改的那次即可。这样可以大大压缩full log中对同一个block的多次记录。这里还会引申出一个问题full log哪里来。

Full log在Change tracking mode中总共有两个来源: 第一个就是前面提到的start recovery; 另外一个是Change tracking mode下segment primary仍然是处于活跃状态的,backends仍然可以处理业务,自然会产生xlog,full log就是在这个过程中产生的,在上层处理业务过程中去做CTL的收集会非常麻烦,但是在xloginsert过程中,只需要识别出感兴趣的日志类型,并在日志插入时直接提取rdata中的的数据页面信息,存入full log。

至此Change tracking log基本上介绍完了,再回顾一下上一篇文章中提到的resync机制,resync manager负责从persistent表中获取需要做sync的表信息,如果是inc sync的话还需要参考CTL中的信息,并将这些信息插入到filerepresync哈希表中。resync worker从hash表中提取信息进行resyncwrite或者incwrite。感兴趣的可以看一下上文中列出的几个函数,对于一个需要做增量的relation而言,只会调用incwrite而不会调用resyncwrite。resyncwrite只会处理full sync,inc的PT表,以及Apend only的catchup,incwrite当然只处理inc的普通表了。

今天重新看这一部分代码时发现了很多细节上的问题,其中一个问题太明显了,而且影响比较大,就给GreenPlum社区提了一下,希望可以解决吧。

2015年还有整整一天的时间就过完了,希望2016年能够有一个好的开始,工作顺利,生活也一切顺利,忙起来也要注意休息,调整好心态,毕竟工作只是生活的一部分,cjjlp.

Good night Sweety, Good night World.

Category: 润物细无声 Tagged: GreenPlum

Comments