初步学习pg_control文件之十一

接前文  初步学习pg_control文件之十,再看这个

XLogRecPtr    prevCheckPoint; /* previous check point record ptr */

发生了checkpoint的时候,肯定要处理的:

/*                            
 * Perform a checkpoint --- either during shutdown, or on-the-fly                            
 *                            
 * flags is a bitwise OR of the following:                            
 *    CHECKPOINT_IS_SHUTDOWN: checkpoint is for database shutdown.                        
 *    CHECKPOINT_END_OF_RECOVERY: checkpoint is for end of WAL recovery.                        
 *    CHECKPOINT_IMMEDIATE: finish the checkpoint ASAP,                        
 *        ignoring checkpoint_completion_target parameter.                    
 *    CHECKPOINT_FORCE: force a checkpoint even if no XLOG activity has occured                        
 *        since the last one (implied by CHECKPOINT_IS_SHUTDOWN or                    
 *        CHECKPOINT_END_OF_RECOVERY).                    
 *                            
 * Note: flags contains other bits, of interest here only for logging purposes.                            
 * In particular note that this routine is synchronous and does not pay                            
 * attention to CHECKPOINT_WAIT.                            
 */                            
void                            
CreateCheckPoint(int flags)                            
{                            
    …                        
                            
    /*                        
     * Update the control file.                        
     */                        
    LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);                        
    if (shutdown)                        
        ControlFile->state = DB_SHUTDOWNED;                    
    ControlFile->prevCheckPoint = ControlFile->checkPoint;                        
    ControlFile->checkPoint = ProcLastRecPtr;                        
    ControlFile->checkPointCopy = checkPoint;                        
    ControlFile->time = (pg_time_t) time(NULL);                        
    /* crash recovery should always recover to the end of WAL */                        
    MemSet(&ControlFile->minRecoveryPoint, 0, sizeof(XLogRecPtr));                        
    UpdateControlFile();                        
    LWLockRelease(ControlFileLock);                        
    …                        
}                            

可是为何要保留这个东西呢,看下面这段代码就知道了:

/*                                        
 * This must be called ONCE during postmaster or standalone-backend startup
 */                                        
void                                        
StartupXLOG(void)                                        
{                                        
    …                                    
    if (read_backup_label(&checkPointLoc, &backupEndRequired))                                    
    {                                    
        …                                
    }                                    
    else                                    
    {                                    
        /*                                
         * Get the last valid checkpoint record.  If the latest one according  
         * to pg_control is broken, try the next-to-last one.                                
         */                                
        checkPointLoc = ControlFile->checkPoint;                                
        RedoStartLSN = ControlFile->checkPointCopy.redo;                                
        record = ReadCheckpointRecord(checkPointLoc, 1);                                
        if (record != NULL)                                
        {                                
            ereport(DEBUG1,                            
                    (errmsg("checkpoint record is at %X/%X",                    
                            checkPointLoc.xlogid, checkPointLoc.xrecoff)));            
        }                                
        else if (StandbyMode)                                
        {                                
            /*                            
             * The last valid checkpoint record required for a streaming                            
             * recovery exists in neither standby nor the primary.                            
             */                            
            ereport(PANIC,                            
                    (errmsg("could not locate a valid checkpoint record")));                    
        }                                
        else                                
        {                                
            checkPointLoc = ControlFile->prevCheckPoint;                            
            record = ReadCheckpointRecord(checkPointLoc, 2);                            
            if (record != NULL)                            
            {                            
                ereport(LOG,                        
                        (errmsg("using previous checkpoint record at %X/%X",                
                              checkPointLoc.xlogid, checkPointLoc.xrecoff)));            
                InRecovery = true;        /* force recovery even if SHUTDOWNED */                
            }                            
            else                            
                ereport(PANIC,                        
                     (errmsg("could not locate a valid checkpoint record")));                    
        }                                
        …                                
    }                                    
    …                                    
    /* REDO */                                    
    if (InRecovery)                                    
    {                                    
        …                                
        /*                                
         * Update pg_control to show that we are recovering and to show the                                
         * selected checkpoint as the place we are starting from. We also mark                                
         * pg_control with any minimum recovery stop point obtained from a                                
         * backup history file.                                
         */                                
        if (InArchiveRecovery)                                
            ControlFile->state = DB_IN_ARCHIVE_RECOVERY;                            
        else                                
        {                                
            ereport(LOG,                            
                    (errmsg("database system was not properly shut down; "                    
                            automatic recovery in progress)));            
            ControlFile->state = DB_IN_CRASH_RECOVERY;                            
        }                                
        ControlFile->prevCheckPoint = ControlFile->checkPoint;                                
        ControlFile->checkPoint = checkPointLoc;                                
        ControlFile->checkPointCopy = checkPoint;                                
        …                                
    }                                    
    …                                    
}                                        

就是说,如果拿不到最好的,就拿到上次的那个checkpoint1点:Get the last valid checkpoint record. If the latest one according  to pg_control is broken, try the next-to-last one.  

此外,我们可以看restartPoint时,也有此处理:

/*                                
 * Establish a restartpoint if possible.                                
 *                                
 * This is similar to CreateCheckPoint, but is used during WAL recovery                                
 * to establish a point from which recovery can roll forward without                                
 * replaying the entire recovery log.                                
 *                                
 * Returns true if a new restartpoint was established. We can only establish                                
 * a restartpoint if we have replayed a safe checkpoint record since last                                
 * restartpoint.                                
 */                                
bool                                
CreateRestartPoint(int flags)                                
{                                
    …                            
    /*                            
     * Update pg_control, using current time.  Check that it still shows                            
     * IN_ARCHIVE_RECOVERY state and an older checkpoint, else do nothing;                            
     * this is a quick hack to make sure nothing really bad happens if somehow                            
     * we get here after the end-of-recovery checkpoint.                            
     */                            
    LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);                            
    if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY &&                            
        XLByteLT(ControlFile->checkPointCopy.redo, lastCheckPoint.redo))                        
    {                            
        ControlFile->prevCheckPoint = ControlFile->checkPoint;                        
        ControlFile->checkPoint = lastCheckPointRecPtr;                        
        ControlFile->checkPointCopy = lastCheckPoint;                        
        ControlFile->time = (pg_time_t) time(NULL);                        
        if (flags & CHECKPOINT_IS_SHUTDOWN)                        
            ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY;                    
        UpdateControlFile();                        
    }                            
    LWLockRelease(ControlFileLock);                            
    …                            
}                                

 

     

posted @ 2013-08-01 15:10  健哥的数据花园  阅读(759)  评论(0编辑  收藏  举报