初步学习pg_control文件之九

简介:

接前文,初步学习pg_control文件之八

来看这个:

pg_time_t    time;            /* time stamp of last pg_control update */

当初初始化的时候,是这样的:

复制代码
/*
 * This func must be called ONCE on system install.  It creates pg_control
 * and the initial XLOG segment.
 */
void
BootStrapXLOG(void)
{
    ...
    CheckPoint    checkPoint;
    ...
    checkPoint.time = (pg_time_t) time(NULL);
    ...

    ControlFile->time = checkPoint.time;
}
复制代码

之后、启动时:

复制代码
/*                                    
 * This must be called ONCE during postmaster or standalone-backend startup                                    
 */                                    
void                                    
StartupXLOG(void)                                    
{                                    
                                    
    …                                
    /* REDO */                                
    if (InRecovery)                                
    {                                
        …                            
        ControlFile->time = (pg_time_t) time(NULL);                            
        …                            
        UpdateControlFile();                            
        …                            
    }                                
    …                                
                                    
    ControlFile->time = (pg_time_t) time(NULL);                                
    UpdateControlFile();                                
                                    
    …                                
}                                    
复制代码

Shutdown的时候:

复制代码
/*                            
 * 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);                        
    …                        
}                            
复制代码

还有一种特别的情况:那就是 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)                                    
{                                    
    …                                
    /*                                
     * If the last checkpoint record we've replayed is already our last                                
     * restartpoint, we can't perform a new restart point. We still update                                
     * minRecoveryPoint in that case, so that if this is a shutdown restart                                
     * point, we won't start up earlier than before. That's not strictly                                
     * necessary, but when hot standby is enabled, it would be rather weird if                                
     * the database opened up for read-only connections at a point-in-time                                
     * before the last shutdown. Such time travel is still possible in case of                                
     * immediate shutdown, though.                                
     *                                
     * We don't explicitly advance minRecoveryPoint when we do create a                                
     * restartpoint. It's assumed that flushing the buffers will do that as a                                
     * side-effect.                                
     */                                
    if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||                                
        XLByteLE(lastCheckPoint.redo, ControlFile->checkPointCopy.redo))                            
    {                                
        XLogRecPtr    InvalidXLogRecPtr = {0, 0};                        
                                    
        ereport(DEBUG2,                            
                (errmsg("skipping restartpoint, already performed at %X/%X",                    
                  lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff)));                    
                                    
        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;                            
    }                                
    …                                
                                    
    /*                                
     * 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();                            
    }                                
    …                                
}                                    
复制代码

那么,何时会触发 RestartPoint呢?

http://www.postgresql.org/docs/9.1/static/wal-configuration.html

复制代码
Checkpoints are points in the sequence of transactions at which it is guaranteed that the heap and index data files have been updated with all information written before the checkpoint. At checkpoint time, all dirty data pages are flushed to disk and a special checkpoint record is written to the log file. (The changes were previously flushed to the WAL files.) In the event of a crash, the crash recovery procedure looks at the latest checkpoint record to determine the point in the log (known as the redo record) from which it should start the REDO operation. Any changes made to data files before that point are guaranteed to be already on disk. Hence, after a checkpoint, log segments preceding the one containing the redo record are no longer needed and can be recycled or removed. (When WAL archiving is being done, the log segments must be archived before being recycled or removed.)

The checkpoint requirement of flushing all dirty data pages to disk can cause a significant I/O load. For this reason, checkpoint activity is throttled so I/O begins at checkpoint start and completes before the next checkpoint starts; this minimizes performance degradation during checkpoints.

The server's background writer process automatically performs a checkpoint every so often. A checkpoint is created every checkpoint_segments log segments, or every checkpoint_timeout seconds, whichever comes first. The default settings are 3 segments and 300 seconds (5 minutes), respectively. It is also possible to force a checkpoint by using the SQL command CHECKPOINT.
复制代码

上面是说 checkpoint。再来看restartpoint:

其实是为了防止recovery动作里再次出错:

复制代码
In archive recovery or standby mode, the server periodically performs restartpoints which are similar to checkpoints in normal operation: the server forces all its state to disk, updates the pg_control file to indicate that the already-processed WAL data need not be scanned again, and then recycles any old log segment files in pg_xlog directory. A restartpoint is triggered if at least one checkpoint record has been replayed and checkpoint_timeout seconds have passed since last restartpoint. In standby mode, a restartpoint is also triggered if checkpoint_segments log segments have been replayed since last restartpoint and at least one checkpoint record has been replayed. Restartpoints can't be performed more frequently than checkpoints in the master because restartpoints can only be performed at checkpoint records.
复制代码

其运行的前提是:archive recovery 或者 standby mode,这都是要用到 archive recovery的。

再看相关代码:

头文件:

复制代码
/*                                        
 * OR-able request flag bits for checkpoints.  The "cause" bits are used only 
 * for logging purposes.  Note: the flags must be defined so that it's   
 * sensible to OR together request flags arising from different requestors. 
 */                                        
                                        
/* These directly affect the behavior of CreateCheckPoint and subsidiaries */                                        
#define CHECKPOINT_IS_SHUTDOWN                    0x0001    /* Checkpoint is for shutdown */  
#define CHECKPOINT_END_OF_RECOVERY                    0x0002        /* Like shutdown checkpoint, 
#define CHECKPOINT_IMMEDIATE                    0x0004    /* Do it without delays */                
#define CHECKPOINT_FORCE                        0x0008    /* Force even if no activity */            
/* These are important to RequestCheckpoint */                                        
#define CHECKPOINT_WAIT                            0x0010    /* Wait for completion */        
/* These indicate the cause of a checkpoint request */                                        
#define CHECKPOINT_CAUSE_XLOG                    0x0020    /* XLOG consumption */                
#define CHECKPOINT_CAUSE_TIME                    0x0040    /* Elapsed time */                
复制代码

shutdown时,要判断是否是在recovery的时候进行的,从而设置一个特殊的DB_SHUTDOWNED_IN_RECOVERY状态:

复制代码
/*                                        
 * This must be called ONCE during postmaster or standalone-backend shutdown                                        
 */                                        
void                                        
ShutdownXLOG(int code, Datum arg)                                        
{                                        
                                                                               
    ereport(LOG,                                    
            (errmsg("shutting down")));                            
                                        
    if (RecoveryInProgress())                                    
        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();                            
                                        
        CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);                                
    }                                    
    ShutdownCLOG();                                    
    ShutdownSUBTRANS();                                    
    ShutdownMultiXact();                                    
                                        
    ereport(LOG,                                    
            (errmsg("database system is shut down")));                            
                                                        
}                                        
复制代码

还有就是 bgwriter也要进行调用:

复制代码
/*                                    
 * Main entry point for bgwriter process                                    
 *                                    
 * This is invoked from BootstrapMain, which has already created the basic                                    
 * execution environment, but not enabled signals yet.                                    
 */                                    
void                                    
BackgroundWriterMain(void)                                    
{                                    
    …                                
    /*                                
     * Loop forever                                
     */                                
    for (;;)                                
    {                                
        bool        do_checkpoint = false;                    
        int            flags = 0;                
        …                            
        if (checkpoint_requested)                            
        {                            
            checkpoint_requested = false;                        
            do_checkpoint = true;                        
            BgWriterStats.m_requested_checkpoints++;                        
        }                            
                                    
        …                            
        /*                            
         * Force a checkpoint if too much time has elapsed since the last one.                            
         * Note that we count a timed checkpoint in stats only when this                            
         * occurs without an external request, but we set the CAUSE_TIME flag                            
         * bit even if there is also an external request.                            
         */                            
        now = (pg_time_t) time(NULL);                            
        elapsed_secs = now - last_checkpoint_time;                            
        if (elapsed_secs >= CheckPointTimeout)                            
        {                            
            if (!do_checkpoint)                        
                BgWriterStats.m_timed_checkpoints++;                    
            do_checkpoint = true;                        
            flags |= CHECKPOINT_CAUSE_TIME;                        
        }                            
                                    
        /*                            
         * Do a checkpoint if requested, otherwise do one cycle of                            
         * dirty-buffer writing.                            
         */                            
        if (do_checkpoint)                            
        {                            
            bool        ckpt_performed = false;                
            bool        do_restartpoint;                
                                    
            …                        
            /*                        
             * Check if we should perform a checkpoint or a restartpoint. As a                        
             * side-effect, RecoveryInProgress() initializes TimeLineID if                        
             * it's not set yet.                        
             */                        
            do_restartpoint = RecoveryInProgress();   /*                        
             * The end-of-recovery checkpoint is a real checkpoint that's                        
             * performed while we're still in recovery.                        
             */                        
            if (flags & CHECKPOINT_END_OF_RECOVERY)                        
                do_restartpoint = false;                    
                                    
            …                        
            /*                        
             * Do the checkpoint.                        
             */                        
            if (!do_restartpoint)                        
            {                        
                CreateCheckPoint(flags);                    
                ckpt_performed = true;                    
            }                        
            else                        
                ckpt_performed = CreateRestartPoint(flags);                    
                                    
            …                        
        }                            
        else                            
            BgBufferSync();                        
        …                            
    }                                
}                                    
复制代码
目录
相关文章
|
Oracle NoSQL 关系型数据库
实时计算 Flink版操作报错之报错:java.lang.ClassNotFoundException: io.debezium.connector.common.RelationalBaseSourceConnector,如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
11月前
|
关系型数据库 分布式数据库 数据库
PostgreSQL+Citus分布式数据库
PostgreSQL+Citus分布式数据库
292 15
|
分布式计算 监控 Hadoop
Hadoop任务执行失败
【7月更文挑战第12天】
563 10
|
11月前
|
SQL 关系型数据库 数据库连接
"Nacos 2.1.0版本数据库配置写入难题破解攻略:一步步教你排查连接、权限和配置问题,重启服务轻松解决!"
【10月更文挑战第23天】在使用Nacos 2.1.0版本时,可能会遇到无法将配置信息写入数据库的问题。本文将引导你逐步解决这一问题,包括检查数据库连接、用户权限、Nacos配置文件,并提供示例代码和详细步骤。通过这些方法,你可以有效解决配置写入失败的问题。
539 0
|
关系型数据库 数据库 PostgreSQL
如何在 Postgres 中重命名列
【8月更文挑战第11天】
592 0
如何在 Postgres 中重命名列
|
NoSQL Redis 数据安全/隐私保护
redis 常见报错和解决方案
redis 常见报错和解决方案
430 1
|
存储 SQL 分布式计算
Java连接阿里云MaxCompute例
要使用Java连接阿里云MaxCompute数据库,首先需在项目中添加MaxCompute JDBC驱动依赖,推荐通过Maven管理。避免在代码中直接写入AccessKey,应使用环境变量或配置文件安全存储。示例代码展示了如何注册驱动、建立连接及执行SQL查询。建议使用RAM用户提升安全性,并根据需要配置时区和公网访问权限。具体步骤和注意事项请参考阿里云官方文档。
888 10
|
网络安全 流计算 Python
实时计算 Flink版操作报错合集之Flink sql-client 针对kafka的protobuf格式数据建表,报错:java.lang.ClassNotFoundException 如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
327 1
|
消息中间件 关系型数据库 网络安全
实时计算 Flink版操作报错合集之Flink sql-client 针对kafka的protobuf格式数据建表,报错:java.lang.ClassNotFoundException 如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
404 1
|
Oracle 关系型数据库 Java
实时计算 Flink版操作报错合集之异常信息显示在Flink中找不到指定的ReplicationSlot如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
572 1