PostgreSQL备机checkpoint
admin
2023-01-27 23:19:40
0

  数据库异常关闭时,数据库关闭时来不及或者没机会做checkpoint,则需要从上一个一致性检查的开始恢复。

    PostgreSQL备机checkpoint是不能产生checkpoint WAL的,因为如果写这样类型的checkpoint的话,就会将接收的WAL打乱,那么日志将混乱,回放会出问题。

    那么问题来了,备机支持checkpoint吗?他的checkpoint怎么做的?

    PostgreSQL为了缩短恢复时间,备机上也支持checkpoint,即CreateRestartPoint。但是其pg_control文件的checkpoint记录的位点是从主机传过来WAL里面的checkpoint记录位置。

1、备机回放

StartupXLOG
    do{
        ...
        RmgrTable[record->xl_rmid].rm_redo(xlogreader);//回放
        ...
        record = ReadRecord(xlogreader, InvalidXLogRecPtr, LOG, false);//读取一个xlog
    } while (record != NULL);

2、回放函数

void
xlog_redo(XLogReaderState *record)
{
    ...
    else if (info == XLOG_CHECKPOINT_SHUTDOWN){
        ...
        memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
        ...
        RecoveryRestartPoint(&checkPoint);
    }else if (info == XLOG_CHECKPOINT_ONLINE){
        ...
        memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
        ...
        RecoveryRestartPoint(&checkPoint);
    }
    ...
}

3、RecoveryRestartPoint

static void
RecoveryRestartPoint(const CheckPoint *checkPoint)
{
    ...
    SpinLockAcquire(&XLogCtl->info_lck);
    XLogCtl->lastCheckPointRecPtr = ReadRecPtr;//ReadRecPtr为读取checkpoint记录后的位置
    XLogCtl->lastCheckPointEndPtr = EndRecPtr;
    XLogCtl->lastCheckPoint = *checkPoint;
    SpinLockRelease(&XLogCtl->info_lck);
}

4、ReadRecPtr赋值

ReadRecord
    for (;;)
    {
        char       *errormsg;

        record = XLogReadRecord(xlogreader, RecPtr, &errormsg);
        ReadRecPtr = xlogreader->ReadRecPtr;
        EndRecPtr = xlogreader->EndRecPtr;
        ...
    }

5、备机createcheckpoint

bool
CreateRestartPoint(int flags)
{

    LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);

    /* Get a local copy of the last safe checkpoint record. */
    SpinLockAcquire(&XLogCtl->info_lck);
    lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;//checkpoint的位置来自XLogCtl->lastCheckPointRecPtr
    lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
    lastCheckPoint = XLogCtl->lastCheckPoint;
    SpinLockRelease(&XLogCtl->info_lck);

    ...

    if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) || lastCheckPoint.redo <= ControlFile->checkPointCopy.redo){
        //回放了最后一个checkpoint记录后,备机再次手动执行checkpoint命令
        UpdateMinRecoveryPoint(InvalidXLogRecPtr, true);
        if (flags & CHECKPOINT_IS_SHUTDOWN){
            LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
            ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY;
            ControlFile->time = (pg_time_t) time(NULL);
            UpdateControlFile();
            LWLockRelease(ControlFileLock);
        }
        LWLockRelease(CheckpointLock);
        return false;
    }
    ...
    LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
    if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY && ControlFile->checkPointCopy.redo < lastCheckPoint.redo){
        ControlFile->prevCheckPoint = ControlFile->checkPoint;
        ControlFile->checkPoint = lastCheckPointRecPtr;//checkpoint的位置
        ControlFile->checkPointCopy = lastCheckPoint;
        ControlFile->time = (pg_time_t) time(NULL);
        ...
        if (flags & CHECKPOINT_IS_SHUTDOWN)
            ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY;
        UpdateControlFile();
    }
    ...

    return true;
}

6、备机shutdown

void
ShutdownXLOG(int code, Datum arg)
{
    /*
     * Signal walsenders to move to stopping state.
     */
    WalSndInitStopping();

    /*
     * Wait for WAL senders to be in stopping state.  This prevents commands
     * from writing new WAL.
     */
    WalSndWaitStopping();

    if (RecoveryInProgress())//备机写checkpoint
        CreateRestartPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
    else
    {
        /*
         * If archiving is enabled, rotate the last XLOG file so that all the
         * remaining records are archived (postmaster wakes up the archiver
         * process one more time at the end of shutdown). The checkpoint
         * record will go to the next XLOG file and won't be archived (yet).
         */
        if (XLogArchivingActive() && XLogArchiveCommandSet())
            RequestXLogSwitch(false);

        CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
    }
    ShutdownCLOG();
    ShutdownCommitTs();
    ShutdownSUBTRANS();
    ShutdownMultiXact();
}

7、总结

PostgreSQL备库也可以写检查点,目的是避免每次重启备库都需要从上一个检查点(由主库产生,在WAL中回放出来的)APPLY后面所有的WAL。但是他记录的checkpoint位点是从主库传过来的。这样的话就有问题了,如果主机很长时间都没有做checkpoint了,备机即使正常关闭,重启时,也会从上一个checkpoint开始恢复,这样也会恢复很长时间;并且多次重启也需要从上一次checkpoint开始重复恢复。

相关内容

热门资讯

德国总理:美国正在被伊朗羞辱 德国之声4月27日报道,德国总理默茨在访问一所学校时表示,在当前的持续冲突中,伊朗领导层正试图羞辱美...
理响中国|“长”歌以行,风云激... 光阴如梭,东方潮阔。这里是中国的长三角,世界的长三角。无论过去、现在还是未来,这片土地都因时代而生,...
白宫:特朗普及其国安团队开会讨... 新华社华盛顿4月27日电 美国白宫新闻秘书莱维特27日在记者会上证实,总统特朗普及其国家安全团队当天...
人民日报刊文:日本放开杀伤性武... 日本放开杀伤性武器出口推高地缘冲突风险(国际论坛)常思纯《人民日报》(2026年04月28日 第 0...
医疗保障法草案二审:明确生育保... 满足多样化健康保障需求本报记者 彭 波4月27日,医疗保障法草案二审稿提请十四届全国人大常委会第二十...
天津一景区发生自转旋翼机事故1... 澎湃新闻记者 吕新文中国民用航空华北地区管理局4月22日公布《豪客通航“10•1”天津长芦汉盐旅游区...
卡塔尔埃米尔与美国总统特朗普通... 当地时间24日,卡塔尔埃米尔塔米姆与美国总统特朗普通电话,重点就中东地区局势以及伊朗与美国谈判问题交...
男子30年前被扣押2859克黄... 澎湃新闻记者 王鑫家住辽宁省大连市的潘永嘉近日向澎湃新闻反映称,三十年前,他在大连周水子机场被盖州市...
商务部:取消反制欧盟两家金融机... 中华人民共和国商务部令二〇二六年 第1号鉴于欧盟已取消对中国两家金融机构的制裁措施,现公布《关于取消...
过去24小时共有5艘船只通过霍... 总台记者当地时间24日获悉,过去24小时内,共有5艘船只通过霍尔木兹海峡,其中包括一艘伊朗油轮。(总...