接前文,初步学习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. 使用Gardener在Google Cloud Platform上创建Kubernetes集群

    Gardener是一个开源项目,github地址: https://github.com/gardener/gardener/ 使用Gardener,我们可以在几分钟之内在GCP, AWS, Azur ...

  2. Jmeter入门17 获取时间点前后一定间隔的时间 __timeShift()

    接口获取时间点前后一定间隔的时间函数: __timeShift(时间格式, 特定时间点(缺省当前时间),时间间隔,地区格式(默认),变量名( 可不填,填写后其他地方用${变量名}引用 )) 举例: 1 ...

  3. BZOJ2730:[HNOI2012]矿场搭建(双连通分量)

    Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...

  4. Codeforces Round #431 (Div. 2)

    A. Odds and Ends Where do odds begin, and where do they end? Where does hope emerge, and will they e ...

  5. Uva 4394 字符串刷子

    题目链接:https://vjudge.net/contest/164840#problem/A 题意:一个字符串刷子,每次可以将一段连续的字符串变成一种颜色,给两个字符串,最少通过几次可以将第一个字 ...

  6. 有趣的npx

    在更新 npm 5.2.0 的时候发现会买一送一,自动安装了 npx. npx 会帮你执行依赖包里的二进制文件,也就是说 npx 会自动查找当前依赖包中的可执行文件, 如果找不到,就会去 PATH 里 ...

  7. 关于In-App Purchase(内购)的注意事项

    前言:关于In-App Purchase(内购)的注意事项 一点注意事项: 内购应该有游客身份的购买选项,不然可能被拒,前一段时间我这边一直是因为没有游客身份购买被拒. 在验证内购结果的时候要注意使用 ...

  8. react setState修改嵌套对象

    在react使用setState过程中,难免会遇到复杂的数据类型,,这里还要提醒一下setState 是异步操作行为,需要setState之后的结果做为参数,请求数据的话,可以配合 async  aw ...

  9. SpringBoot非官方教程 | 终章:文章汇总

    转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot-all/ 本文出自方志朋的博客 SpringBo ...

  10. RMAN备份与恢复(三)--备份相关概念

    (1)备份对象 可以使用RMAN进行的备份对象如下: --整个数据库:备份所有的数据文件和控制文件: --数据文件:备份指定的一个或多个数据文件: --表空间:备份指定的一个或多个表空间: --归档重 ...