接前文,初步学习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, , 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 = {, }; 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 = ;

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();

}
}

初步学习pg_control文件之九的更多相关文章

  1. 初步学习pg_control文件之十

    接前文 初步学习pg_control文件之九 看下面这个 XLogRecPtr checkPoint; /* last check point record ptr */ 看看这个pointer究竟保 ...

  2. 初步学习pg_control文件之十五

    接前文  初步学习pg_control文件之十四 再看如下这个: int MaxConnections; 应该说,它是一个参考值,在global.c中有如下定义 /* * Primary determ ...

  3. 初步学习pg_control文件之十四

    接前文 初步学习pg_control文件之十三 看如下几个: /* * Parameter settings that determine if the WAL can be used for arc ...

  4. 初步学习pg_control文件之十三

    接前文,初步学习pg_control文件之十二 看这个: * backupStartPoint is the redo pointer of the backup start checkpoint, ...

  5. 初步学习pg_control文件之十二

    接前问,初步学习pg_control文件之十一,再来看下面这个 XLogRecPtr minRecoveryPoint; 看其注释: * minRecoveryPoint is updated to ...

  6. 初步学习pg_control文件之十一

    接前文  初步学习pg_control文件之十,再看这个 XLogRecPtr prevCheckPoint; /* previous check point record ptr */ 发生了che ...

  7. 初步学习pg_control文件之八

    接前文  初步学习pg_control文件之七  继续 看:catalog_version_no 代码如下: static void WriteControlFile(void) { ... /* * ...

  8. 初步学习pg_control文件之七

    接前文 初步学习pg_control文件之六  看   pg_control_version 以PostgreSQL9.1.1为了,其HISTORY文件中有如下的内容: Release Release ...

  9. 初步学习pg_control文件之六

    接前文:初步学习pg_control文件之五 ,DB_IN_ARCHIVE_RECOVERY何时出现? 看代码:如果recovery.conf文件存在,则返回 InArchiveRecovery = ...

随机推荐

  1. May 15th 2017 Week 20th Monday

    Life is a flower of which love is the honey. 人生是花朵,爱情是花蜜. Not every life can be a flower, not every ...

  2. CRUD全栈式编程架构之服务层的设计

    服务层代码 首先我先放出2个主要类的代码再分别讲解 接口 using System; using System.Collections.Generic; using System.Linq; usin ...

  3. Bootstrap Table的使用小结

    1.Jquery中的一些东西学习一下子,补充完善一下,毕竟有些时候没有使用到 这个方式很有用,在使用bootstrap table的时候,选择当前已经选择的节点的事件中的ID的值 当前rows中有很多 ...

  4. ACM-ICPC(10/23)

    贪心 区间相关问题 选择不相交区间: hdu 2037 给定一些区间,选择尽量多的区间,他们互相不交叉.(活动安排问题) 分析:贪心思路是解决活动安排问题的好方案. 按照区间右端点排序,从前往后遍历, ...

  5. POJ 3694 无向图的桥

    Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10404   Accepted: 3873 Descript ...

  6. (第五场)G max 【数论】

    题目链接:https://www.nowcoder.com/acm/contest/143/G 题目描述 Give two positive integer c, n. You need to fin ...

  7. selenium定位学习回顾

    之前已经专门学过了定位,但后来因为浏览器比较方便,可以直接复制xpath和css进行定位,个人觉得自己快遗忘了这块,所以专门来回顾一下, 顺便记录一下,以便后期查看. 进行web页面自动化测试,对页面 ...

  8. 【转】ConcurrentHashMap原理分析(1.7与1.8)

    https://www.cnblogs.com/study-everyday/p/6430462.html 前言 以前写过介绍HashMap的文章,文中提到过HashMap在put的时候,插入的元素超 ...

  9. 【题解】洛谷P1445 [Violet]樱花 (推导+约数和)

    洛谷P1445:https://www.luogu.org/problemnew/show/P1445 推导过程 1/x+1/y=1/n! 设y=n!+k(k∈N∗) 1/x​+1/(n!+k)​=1 ...

  10. js面向对象轮播图写法

    ;;}         ,,,;}         ];     ].].;     ){             ;             ;         }) } Banner.protot ...