ao表的同步是个强同步的过程,数据在更新发生时即同步到mirror,primary和mirror时刻保持着数据一致性。另一方面,事务提交时会更新ao表文件的尾指针信息,并同步到备库。这样事务提交后,mirror肯定可以看到所有已提交的数据。所以primary failover切换后ao表数据不会丢失,不影响事务的一致性。
heap表的数据的更新会写入相应的xlog,同时确保heap表数据页的同步必须在对应的xlog同步完成后才能进行。
你可能有疑问:heap表的数据更新同步到mirror是个异步的过程,那么会不会出现一个事务提交了,heap表数据更新还没有来得及同步到mirror,这时候primary failover切换到mirror,导致heap表数据丢失?当然不会的,虽然heap表数据同步是一个异步的过程,但是xlog的同步却是一个强同步的过程。primary failover切换到mirror之后,mirror上面的xlog和primary的xlog完全一致,这时候mirror会启动startup进程,进入recovery模式,应用xlog,所以即便heap表数据没有同步过来,mirror也会通过xlog将这些没有过来的数据恢复。
其他文件的更新,其实不需要实时同步。切换时mirror会回放xlog,恢复这些文件的内容。
这样,如果primary与mirror保持同步,上述顺序保证了任何时间点mirror节点的数据都能达到一致。但是,假如出现了网络阻塞或者mirror宕机的情况,数据就无法及时同步到mirror。此时,如果primary在更新数据时,等待数据被同步到mirror,就会被阻塞,而无法继续提供服务。为解决这个问题,greenplum提供了异常处理机制。
此处所说的对网络阻塞或mirror宕机异常情况的处理,其实就是greenplum所谓的change tracking机制。在primary向mirror同步数据的时候,如果mirror长时间没有回应primary,那么primary将会认为mirror挂掉,这个时候master将会把系统表gp_segment_configuration里面的mirror状态(status)置为’d’,同时把primary的模式(mode)置为’c’,而这个’c’模式就是changetracing mode。primary进入change tracking状态后,不会再试图同步数据到mirror(每次有数据更改时会调用filerepprimary_ismirroringrequired进行检查是否需要同步)。
primary进入changetracing mode之后,每次更新数据产生的xlog,会被立即解析成数据更新记录,放入到change log文件里面(参见<code>changetracking_addrecordfromxlog</code>函数)。change log文件在pg_changetracking/目录下:
changetracing信息具体记录在ct_log_full文件里面,文件记录的核心信息是当前的数据更新在xlog中的位置,文件内容经过解析之后如下:
change log里面只存放heap表的修改信息。ao表的更新信息存放在特定的表中,无需另外记录。而xlog和普通文件,都完整保存在primary的数据目录下,无需记录修改信息(具体原因在异常恢复的说明中有介绍)。
change log其实是存放的heap表更改页的元数据信息,并未存放更改的实际内容。所以它并不占用太多存储空间,另外它还可以对相同页上的修改进行合并,进一步压缩大小,减少恢复时间(参见<code>filerepprimary_runchangetrackingcompacting</code>函数)。
那么,mirror在宕机后重启或网络拥塞发生后恢复正常了,重新连接到primary后,如何通过change log恢复同步呢?
异常恢复
在异常情况消失后,需要通过执行<code>gprecoverseg -a</code>命令来恢复同步。下面我们还是把数据分成4类来说明这个过程总数据同步恢复的过程。
heap表恢复
当我们执行<code>gprecoverseg -a</code>命令恢复mirror时,primary的resync进程通过change log信息,再结合xlog,将积累的数据变更再次同步给mirror。
具体步骤如下:
resync manager进程通过调用一系列函数filerepresyncmanager_inresynctransition->persistentfilesysobj_markpageincrementalfromchangelog->persistentfilesysobj_markpageincremental->persistentfilesysobj_updatetuplepageincremental,将需要更新的page的信息加入到resyncentry同步队列中。
resync worker进程从resyncentry队列中取出需要恢复到mirror的任务,通过调用一系列函数filerepprimary_resyncbufferpoolincrementalwrite->smgrwrite将page写到缓冲区中,再通过上面的方法构造消息发送到mirror。
ao表恢复
因为ao表不写xlog,所以change log中并没有记录ao表更新操作。那么mirror是如何将ao表恢复到和primary数据一致呢?其实在gp catalog中有一张gp_persistent_relation_node表,里面记录了ao表同步到mirror的最后一次文件位置(mirror_append_only_loss_eof),以及当前文件位置(mirror_append_only_loss_eof)。ao表文件位置的更新是在finishpreparedtransaction函数完成的(执行commit prepared or rollback prepared)。最后resync worker进程将会把未同步到mirror的增量数据再次通过消息同步给它,最终达到primary和mirror的数据一致性。
xlog文件的恢复
我们知道,xlog文件其实都保存在primary的pg_xlog目录下。在异常恢复时,把改目录下的文件直接发送到mirror即可。需要注意的是,异常期间是可以正常删除或规定xlog文件的,这是因为,所有的heap表和ao表的修改都已经被保存下来了,无需另外保留一份xlog来恢复数据。
其他文件的恢复
其他文件(pg_control, pg_clog, pg_mutitrans等文件)也和xlog文件一样,在恢复时直接全部发送到mirror,具体参见<code>filerepresyncmanager_resyncflatfiles</code>函数。