问题背景
walminer工具的用户反馈来一个问题,不管添加了多少wal日志,想要的wal文件的解析结果总是有未解析出的部分。
分析问题
分析问题发现,checkpoint wal记录之后对某个数据page进行修改时,没有对这个page执行FPW(疑问)。
然后去看wal文件中的checkpoint记录(如下图),
发现checkpoint记录的lsn与redo位置不一致,一时没有想清楚这样的原因。最后想明白了checkpoint是一个需要花费一定时间的行为。lsn记录的是写这条wal记录的时候的wal位置,redo记录的是checkpoint开始时的wal位置。因此之前的疑问就解决了:FPW行为发生在checkpoint开始之后,而不是结束之后。我在遇到checkpoint wal记录时执行了对程序内部FPW page的清理操作。因此会出现过早清理FPW page的问题,导致有一些wal记录无法解析。
问题解决
应该根据每一个FPW page的lsn和checkpoint点的redo关系进行判断是否要删除这个FPW。
目前没有时间做,暂时移除FPW page的中间清理机制。
知识点记录
如下 是PG checkpoint的结构体,里面有一个redo属性,这个属性记录了checkpoint行为开始时数据库的最大LSN
typedef struct CheckPoint
{
XLogRecPtr redo; /* next RecPtr available when we began to
* create CheckPoint (i.e. REDO start point) */
TimeLineID ThisTimeLineID; /* current TLI */
TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
* timeline (equals ThisTimeLineID otherwise) */
bool fullPageWrites; /* current full_page_writes */
uint32 nextXidEpoch; /* higher-order bits of nextXid */
TransactionId nextXid; /* next free XID */
Oid nextOid; /* next free OID */
MultiXactId nextMulti; /* next free MultiXactId */
MultiXactOffset nextMultiOffset; /* next free MultiXact offset */
TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
Oid oldestXidDB; /* database with minimum datfrozenxid */
MultiXactId oldestMulti; /* cluster-wide minimum datminmxid */
Oid oldestMultiDB; /* database with minimum datminmxid */
pg_time_t time; /* time stamp of checkpoint */
TransactionId oldestCommitTsXid; /* oldest Xid with valid commit
* timestamp */
TransactionId newestCommitTsXid; /* newest Xid with valid commit
* timestamp */
/*
* Oldest XID still running. This is only needed to initialize hot standby
* mode from an online checkpoint, so we only bother calculating this for
* online checkpoints and only when wal_level is replica. Otherwise it's
* set to InvalidTransactionId.
*/
TransactionId oldestActiveXid;
} CheckPoint;
每一个wal记录都有自己的LSN,checkpoint的wal记录也有。
checkpoint会花费一定时间,checkpoint动作完成后才会记录checkpoint的wal记录,因此redo与lsn有一定的差距。