初步学习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文件之九的更多相关文章
- 初步学习pg_control文件之十
接前文 初步学习pg_control文件之九 看下面这个 XLogRecPtr checkPoint; /* last check point record ptr */ 看看这个pointer究竟保 ...
- 初步学习pg_control文件之十五
接前文 初步学习pg_control文件之十四 再看如下这个: int MaxConnections; 应该说,它是一个参考值,在global.c中有如下定义 /* * Primary determ ...
- 初步学习pg_control文件之十四
接前文 初步学习pg_control文件之十三 看如下几个: /* * Parameter settings that determine if the WAL can be used for arc ...
- 初步学习pg_control文件之十三
接前文,初步学习pg_control文件之十二 看这个: * backupStartPoint is the redo pointer of the backup start checkpoint, ...
- 初步学习pg_control文件之十二
接前问,初步学习pg_control文件之十一,再来看下面这个 XLogRecPtr minRecoveryPoint; 看其注释: * minRecoveryPoint is updated to ...
- 初步学习pg_control文件之十一
接前文 初步学习pg_control文件之十,再看这个 XLogRecPtr prevCheckPoint; /* previous check point record ptr */ 发生了che ...
- 初步学习pg_control文件之八
接前文 初步学习pg_control文件之七 继续 看:catalog_version_no 代码如下: static void WriteControlFile(void) { ... /* * ...
- 初步学习pg_control文件之七
接前文 初步学习pg_control文件之六 看 pg_control_version 以PostgreSQL9.1.1为了,其HISTORY文件中有如下的内容: Release Release ...
- 初步学习pg_control文件之六
接前文:初步学习pg_control文件之五 ,DB_IN_ARCHIVE_RECOVERY何时出现? 看代码:如果recovery.conf文件存在,则返回 InArchiveRecovery = ...
随机推荐
- 函数名: lseek
函数名: lseek 功 能: 移动文件读/写指针 头文件:#include <sys/types.h> #include <unistd.h> 用 法: off_t lsee ...
- 如何在Kubernetes里给PostgreSQL创建secret
创建一个initdb.sql文件,输入如下内容: -- This is a postgres initialization script for the postgres container. -- ...
- 找出OData service出错根源的小技巧
SAP的Fiori应用是通过OData和后台交互的.在使用Fiori应用时您可能会遇到这样的错误消息: 这个错误消息没有包含有助于partner或者客户定位问题根源的线索. 下面是如何在后台找出问题根 ...
- C4C Cloud Application Studio做ABSL开发的一些性能方面的最佳实践
Stefan Hagen在博文SAP Cloud Application Studio Performance Best Practices里介绍了在C4C里使用Cloud Application S ...
- OC 枚举
void test() { // 定义一种枚举类型 enum Season {spring, summer, autumn, winter}; // 定义一个枚举变量s enum Season s = ...
- Android 高级UI设计笔记09:Android实现无限滚动列表
1. 无限滚动列表应用场景: ListView和GridView已经成为原生的Android应用实现中两个最流行的设计模式.目前,这些模式被大量的开发者使用,主要是因为他们是简单而直接的实现,同时他们 ...
- HDU 3336 KMP
题意:求每一个前缀,跟前缀相同的每个子串. 此题:网上很多都是假程序,不过也AC了,的确我测试几个案例之后的的确确是存在这个问题. 分析:每一个前缀,可以考虑KMP,f失配指针,如何求得它出现了多少次 ...
- sqlite迁移mysql(导入导出数据)
第一步,将数据导出 进入sqlite3->.open [打开文件路径]->.cd [要保存的路径]->.output [导出文件名字.sql]->.dump 等待导出成功后,就 ...
- 【洛谷P2426】删数
删数 题目链接 一道裸的区间DP,f[l][r]表示剩下区间[l,r]时的最大价值 可以由f[1~l-1][r]和f[l][r+1~n]转移过来 详见代码: #include<algorithm ...
- c#正则表达式最简demo
各个语言的正则表达式规则略有不同 项目中用到,所以将这个最简单的demo记录 using System; using System.Collections.Generic; using System. ...