初步学习pg_control文件之五

接前文 初步学习pg_control文件之四,继续看何时出现  DB_IN_CRASH_RECOVERY:

看下面代码就比较清楚了:如果对 InArchiveRecovery 判断值为假,而且 读取出来pg_control文件的 state不是 SHUTDOWNED状态,表明当初没有来得及把SHUTDOWNED状态写入到pg_control文件,那么就是说系统已经崩溃了。

/*                                    
 * This must be called ONCE during postmaster or standalone-backend startup                                    
 */                                    
void                                    
StartupXLOG(void)                                    
{                                    
                                    
    …                                
    /*                                
     * Read control file and check XLOG status looks valid.                                
     *                                
     * Note: in most control paths, *ControlFile is already valid and we need                                
     * not do ReadControlFile() here, but might as well do it to be sure.                                
     */                                
    ReadControlFile();                                
                                    
    …                                
    /*                                
     * Check whether we need to force recovery from WAL.  If it appears to                                
     * have been a clean shutdown and we did not have a recovery.conf file,                                
     * then assume no recovery needed.                                
     */                                
    if (XLByteLT(checkPoint.redo, RecPtr))                                
    {                                
        if (wasShutdown)                            
            ereport(PANIC,                        
                    (errmsg("invalid redo record in shutdown checkpoint")));                
        InRecovery = true;                            
    }                                
    else if (ControlFile->state != DB_SHUTDOWNED)                                
        InRecovery = true;                            
    else if (InArchiveRecovery)                                
    {                                
        /* force recovery due to presence of recovery.conf */                            
        InRecovery = true;                            
    }                                
                                    
    /* 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;                        
        }                            
        …                            
    }                                
    …                                
}                                    

然而,还需要把整个拼图补上一块,在正常关闭的时候,是如何把SHUTDOWNED状态写入到pg_control文件中的。 

注意下面出现的updateControlFile:

/*                            
 * 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)                            
{                            
    …                        
    if (shutdown)                        
    {                        
        LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);                    
        ControlFile->state = DB_SHUTDOWNING;                    
        ControlFile->time = (pg_time_t) time(NULL);                    
        UpdateControlFile();                    
        LWLockRelease(ControlFileLock);                    
    }                        
                            
    …                        
    /*                        
     * 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);                        
    …                        
}                            

  

原文地址:https://www.cnblogs.com/gaojian/p/3227725.html