之前在读SwitchWAL这块代码的时候,对其中的很多处理点是知其然但是不知其所以然。经过最近的重新深入思索,对其中的很多处理点都明白了其处理原因,这里简单记录一下:
SwitchWAL:通常是当DB当前所有alive WAL的总大小达到约束时,由Write thread上的leader线程在执行WAL写入之前调用以使所有alive WAL的总大小满足约束。该函数在执行完毕之后会使得oldest alive WAL能够满足被回收删除的条件,而本函数实际上不会执行对该oldest alive WAL的清理操作。
1、SwitchWAL流程中为什么要执行column family flush?
要使得oldest alive WAL能够被回收删除,那么其必须不能含有任意一个cf的还未flush的数据(换句话说,就是该WAL中对应到memtable的所有数据都已经被flush到SST),否则,如果该WAL被回收删除之后,其对应到memtable的数据仍存在未被flush到SST的部分,那么就可能导致数据丢失(如:DB不是正常退出、DB进程crash等等)。
2、是否需要对所有cf执行flush:
不然,只需要对那些该WAL可能还含有未flush到SST数据的cf执行flush即可,这可以通过将含有cf未flush数据的最老WAL文件号(即cf的OldestLogToKeep,任何大于等于该文件号的WAL都可能含有对应cf未flush数据)和该WAL进行比较确定需要flush的cf,满足: cf的oldest_alive_log >= OldestLogToKeep ,那么该cf需要执行flush,否则不需要执行flush。
3、为什么要对需要flush的cf执行SwitchMemtable:
这是因为oldest_alive_log对应WAL内的数据可能在cf当前的mutable memtable以及immutable memtables上(实际上[oldest_alive_log,active WAL]之间的所有WAL都是如此)。要使得oldest_alive_log满足回收删除条件(不含有任意一个cf的还未flush的数据),那么就必须将cf当前的mutable memtable以及immutable memtables执行flush任务,那么自然就需要为cf创建一个新的mutable memtable以处理后续的写入请求。
4、为什么oldest_alive_log到最新active WAL(inclusive)之间的所有WAL中的数据可能在cf当前的mutable memtable以及immutable memtables上:
这是因为在计算需要flush的cf时,是通过比较cf的OldestLogToKeep是否满足:OldestLogToKeep <= oldest_alive_log来确定。cf的OldestLogToKeep表示含有该cf未flush数据的最老的WAL文件号,任何比OldestLogToKeep小的WAL文件对该cf来说都可以被删除,而大于等于OldestLogToKeep的WAL文件,则可能含有该cf还未flush的数据。
总结
以上就是SwitchWAL流程中一些关键处理点以及对应的原因分析,在SwitchMemtable流程中同样存在一些难以理解的处理点,后面的文章中进一步分析。☺