PostgreSQL如何删除不使用的xlog文件(2)

#define UsableBytesInPage (XLOG_BLCKSZ - SizeOfXLogShortPHD)//注意:不是文件第一页
#define UsableBytesInSegment ((XLOG_SEG_SIZE / XLOG_BLCKSZ) * UsableBytesInPage - (SizeOfXLogLongPHD - SizeOfXLogShortPHD))

3、函数XLogBytePosToRecPtr

static XLogRecPtr
XLogBytePosToRecPtr(uint64 bytepos)
{

//bytepos:不包括xlog页的页头等额外字节占用的大小
    fullsegs = bytepos / UsableBytesInSegment;
    bytesleft = bytepos % UsableBytesInSegment;
    /*
    1、如果bytesleft < XLOG_BLCKSZ-32,则表示定位到第一页上,则文件偏移值跳过第一页页头大小
    2、如果bytesleft >= XLOG_BLCKSZ-32,则表示定位不是第一页
    */
    if (bytesleft < XLOG_BLCKSZ - SizeOfXLogLongPHD){
        /* fits on first page of segment */
        seg_offset = bytesleft + SizeOfXLogLongPHD;
    }else{
        /* account for the first page on segment with long header */
        seg_offset = XLOG_BLCKSZ;//先跳过第一页
        bytesleft -= XLOG_BLCKSZ - SizeOfXLogLongPHD;//去掉第一页存放XLOG的大小

fullpages = bytesleft / UsableBytesInPage;//剩下的需要几个页
        bytesleft = bytesleft % UsableBytesInPage;//剩下的偏移
        //  文件偏移=第一页大小+剩下的几个页大小+剩下的偏移+最后一页的页头
        seg_offset += fullpages * XLOG_BLCKSZ + bytesleft + SizeOfXLogShortPHD;
    }
    //result=(fullsegs) * XLOG_SEG_SIZE + seg_offset
    XLogSegNoOffsetToRecPtr(fullsegs, seg_offset, result);
    return result;
}


4、函数KeepLogSeg

static void
KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
{
    //segno为当前xlog即将插入位置在第几个文件上
    XLByteToSeg(recptr, segno);
    //XLogCtl->replicationSlotMinLSN;备机上请求预留的最小值?
    keep = XLogGetReplicationSlotMinimumLSN();
    /* compute limit for wal_keep_segments first */
    if (wal_keep_segments > 0){
        /*
        首先计算wal_keep_segments得到的限制:
        1、比如wal_keep_segments值是10,若当前insert的位置的文件号segno为5,那么向前推进到1
        2、否则向前推进wal_keep_segments后的segno前的可删除
        */
        if (segno <= wal_keep_segments)
            segno = 1;
        else
            segno = segno - wal_keep_segments;
    }

/* then check whether slots limit removal further */
    //计算slots限制,如果其算出的值小于wal_keep_segments计算出的值,则需要使用slotSegNo,slots还有用,不能删除
    if (max_replication_slots > 0 && keep != InvalidXLogRecPtr){
        XLByteToSeg(keep, slotSegNo);
        if (slotSegNo <= 0)
            segno = 1;
        else if (slotSegNo < segno)
            segno = slotSegNo;
    }

/* don't delete WAL segments newer than the calculated segment */
    if (segno < *logSegNo)
        *logSegNo = segno;
    //note:
    //如果计算出的segno比上次checkpoint时的文件号logSegNo还有小,则取这次计算的segno
    //如果计算出的segno比上次checkpoint时的文件号logSegNo大,则取上次checkpoint时的文件号。
    //因为恢复时如果是主机,读取最新checkpoint记录失败后,会读取上一次checkpoint记录,如果上次checkpoint的文件被删除,这里就读取不到记录了
}
5、函数RemoveOldXlogFiles

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/0fc1fde7e66660927d6c939ec2a0a02d.html