接前问,初步学习pg_control文件之十一,再来看下面这个

XLogRecPtr    minRecoveryPoint;

看其注释:

     * minRecoveryPoint is updated to the latest replayed LSN whenever we
* flush a data change during archive recovery. That guards against
* starting archive recovery, aborting it, and restarting with an earlier
* stop location. If we've already flushed data changes from WAL record X
* to disk, we mustn't start up until we reach X again. Zero when not
* doing archive recovery.

看来,是为了防止出现重复执行重做日志...它强调的是在 archive recovery的情况下。

启动时,如果处于Recovery状态,则要进行设置:

/*
* This must be called ONCE during postmaster or standalone-backend startup
*/
void
StartupXLOG(void)
{

CheckPoint checkPoint;

/*
* 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(); if (ControlFile->state < DB_SHUTDOWNED ||
ControlFile->state > DB_IN_PRODUCTION ||
!XRecOffIsValid(ControlFile->checkPoint.xrecoff))
ereport(FATAL,
(errmsg("control file contains invalid data")));
… /* REDO */
if (InRecovery)
{

if (InArchiveRecovery)
{
/* initialize minRecoveryPoint if not set yet */
if (XLByteLT(ControlFile->minRecoveryPoint, checkPoint.redo))
ControlFile->minRecoveryPoint = checkPoint.redo;
}

}

}

在xlogredo函数中得到处理:

/*
* XLOG resource manager's routines
*
* Definitions of info values are in include/catalog/pg_control.h, though
* not all record types are related to control file updates.
*/
void
xlog_redo(XLogRecPtr lsn, XLogRecord *record)
{

if (info == XLOG_NEXTOID)
{

}

else if (info == XLOG_BACKUP_END)
{

if (XLByteEQ(ControlFile->backupStartPoint, startpoint))
{
/*
* We have reached the end of base backup, the point where
* pg_stop_backup() was done. The data on disk is now consistent.
* Reset backupStartPoint, and update minRecoveryPoint to make
* sure we don't allow starting up at an earlier point even if
* recovery is stopped and restarted soon after this.
*/

LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); if (XLByteLT(ControlFile->minRecoveryPoint, lsn))
ControlFile->minRecoveryPoint = lsn;
MemSet(&ControlFile->backupStartPoint, , sizeof(XLogRecPtr));
UpdateControlFile(); LWLockRelease(ControlFileLock);
}
}
else if (info == XLOG_PARAMETER_CHANGE)
{

LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
ControlFile->MaxConnections = xlrec.MaxConnections;
ControlFile->max_prepared_xacts = xlrec.max_prepared_xacts;
ControlFile->max_locks_per_xact = xlrec.max_locks_per_xact;
ControlFile->wal_level = xlrec.wal_level; /*
* Update minRecoveryPoint to ensure that if recovery is aborted, we
* recover back up to this point before allowing hot standby again.
* This is particularly important if wal_level was set to 'archive'
* before, and is now 'hot_standby', to ensure you don't run queries
* against the WAL preceding the wal_level change. Same applies to
* decreasing max_* settings.
*/
minRecoveryPoint = ControlFile->minRecoveryPoint;
if ((minRecoveryPoint.xlogid != || minRecoveryPoint.xrecoff != )
&& XLByteLT(minRecoveryPoint, lsn))
{
ControlFile->minRecoveryPoint = lsn;
} UpdateControlFile();
LWLockRelease(ControlFileLock);

}
}

再就是checkpoint发生的时候,也做了处理:

CreateCheckPoint -->XLogFlush--> UpdateMinRecoveryPoint

/*
* 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)
{

recptr = XLogInsert(RM_XLOG_ID,
shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
XLOG_CHECKPOINT_ONLINE,
&rdata); XLogFlush(recptr);

}
/*
* Ensure that all XLOG data through the given position is flushed to disk.
*
* NOTE: this differs from XLogWrite mainly in that the WALWriteLock is not
* already held, and we try to avoid acquiring it if possible.
*/
void
XLogFlush(XLogRecPtr record)
{
XLogRecPtr WriteRqstPtr;
XLogwrtRqst WriteRqst; /*
* During REDO, we are reading not writing WAL. Therefore, instead of
* trying to flush the WAL, we should update minRecoveryPoint instead. We
* test XLogInsertAllowed(), not InRecovery, because we need the bgwriter
* to act this way too, and because when the bgwriter tries to write the
* end-of-recovery checkpoint, it should indeed flush.
*/
if (!XLogInsertAllowed())
{
UpdateMinRecoveryPoint(record, false);
return;
} /* Quick exit if already known flushed */
if (XLByteLE(record, LogwrtResult.Flush))
return; …
}
/*
* Advance minRecoveryPoint in control file.
* If we crash during recovery, we must reach this point again before the
* database is consistent.
* If 'force' is true, 'lsn' argument is ignored. Otherwise, minRecoveryPoint
* is only updated if it's not already greater than or equal to 'lsn'.
*/
static void
UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
{

/*
* An invalid minRecoveryPoint means that we need to recover all the WAL,
* i.e., we're doing crash recovery. We never modify the control file's
* value in that case, so we can short-circuit future checks here too.
*/
if (minRecoveryPoint.xlogid == && minRecoveryPoint.xrecoff == )
updateMinRecoveryPoint = false;
else if (force || XLByteLT(minRecoveryPoint, lsn))
{
/* use volatile pointer to prevent code rearrangement */
volatile XLogCtlData *xlogctl = XLogCtl;
XLogRecPtr newMinRecoveryPoint; /*
* To avoid having to update the control file too often, we update it
* all the way to the last record being replayed, even though 'lsn'
* would suffice for correctness. This also allows the 'force' case
* to not need a valid 'lsn' value.
*
* Another important reason for doing it this way is that the passed
* 'lsn' value could be bogus, i.e., past the end of available WAL, if
* the caller got it from a corrupted heap page. Accepting such a
* value as the min recovery point would prevent us from coming up at
* all. Instead, we just log a warning and continue with recovery.
* (See also the comments about corrupt LSNs in XLogFlush.)
*/
SpinLockAcquire(&xlogctl->info_lck);
newMinRecoveryPoint = xlogctl->replayEndRecPtr;
SpinLockRelease(&xlogctl->info_lck); if (!force && XLByteLT(newMinRecoveryPoint, lsn))
elog(WARNING,
"xlog min recovery request %X/%X is past current point %X/%X",
lsn.xlogid, lsn.xrecoff,
newMinRecoveryPoint.xlogid, newMinRecoveryPoint.xrecoff); /* update control file */
if (XLByteLT(ControlFile->minRecoveryPoint, newMinRecoveryPoint))
{
ControlFile->minRecoveryPoint = newMinRecoveryPoint;
UpdateControlFile();
minRecoveryPoint = newMinRecoveryPoint; ereport(DEBUG2,
(errmsg("updated min recovery point to %X/%X",
minRecoveryPoint.xlogid, minRecoveryPoint.xrecoff)));
}
}
LWLockRelease(ControlFileLock);
}

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

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

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

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

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

  3. 初步学习pg_control文件之十

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

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

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

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

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

  6. 初步学习pg_control文件之三

    接前文,初步学习pg_control文件之二 继续学习: 研究 DBState,先研究 DB_IN_PRODUCTION ,看它如何出现: 它出现在启动Postmaster时运行的函数处: /* * ...

  7. 初步学习pg_control文件之九

    接前文,初步学习pg_control文件之八 来看这个: pg_time_t time; /* time stamp of last pg_control update */ 当初初始化的时候,是这样 ...

  8. 初步学习pg_control文件之八

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

  9. 初步学习pg_control文件之七

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

随机推荐

  1. 【mysql案例】mysql5.6.14配置my.cnf多实例,mysql_install_db初始化不读取my.cnf配置文件

    1.1.1. mysql5.6.14多实例my.cnf时,初始化不读取my.cnf配置文件 [环境描写叙述] 在多实例配置的/etc/my.cnf环境中,运行mysql_install_db后.启动M ...

  2. CodeForces 30C Shooting Gallery 简单dp

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qq574857122/article/details/36944227 题目链接:点击打开链接 给定 ...

  3. HDU 1757 A Simple Math Problem 【矩阵经典7 构造矩阵递推式】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=1757 A Simple Math Problem Time Limit: 3000/1000 MS (J ...

  4. POJ 3621 Sightseeing Cows 【01分数规划+spfa判正环】

    题目链接:http://poj.org/problem?id=3621 Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total ...

  5. [19/03/12-星期二] 数组_遍历(for-each)&复制&java.util.Arrays类

    一.遍历 for-each即增强for循环,是JDK1.5新增加的功能,专门用于读取数组或集合中所有的元素,即对数组进行遍历. //数组遍历 for-each public class Test_03 ...

  6. spring boot Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration

    java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @Context ...

  7. Latex 编辑器安装

    MiKTex + TexStudio 1. 下载安装MiKTex,从http://www.miktex.org/下载basic-miktex-2.9.5872-x64.exe,一路默认安装... 或者 ...

  8. php如何实现登陆后返回原页面

    访问网站页面时,有的页面需要授权才能访问,这时候就会要求用户登录,跳转到登录页面login.php,怎么实现登录后返回到刚才访问的页面项目需求 访问网站页面时,有的页面需要授权才能访问,这时候就会要求 ...

  9. 数据库——MySQL

    MySQL是一个关系型数据库管理系统,是一个基于socket编写的C/S架构的软件. mysql服务端软件即mysqld帮我们管理好文件夹以及文件,前提是作为使用者的我们,需要下载mysql的客户端, ...

  10. Oracle客户端与Toad、plsql developer安装

    (一)oracle client与oracle instant client比较 当我们要使用Toad.plsql developer等工具连接数据库时,首先需要在自己的电脑上安装oracle cli ...