PostgreSQL状态变迁

typedef enum DBState
{
	DB_STARTUP = 0,
	DB_SHUTDOWNED,
	DB_SHUTDOWNED_IN_RECOVERY,
	DB_SHUTDOWNING,
	DB_IN_CRASH_RECOVERY,
	DB_IN_ARCHIVE_RECOVERY,
	DB_IN_PRODUCTION
} DBState;

PostgreSQL启动以及关闭或运行过程中的状态包括以上七种。在pg_controldata获取的内容Database cluster state一栏显示的是DB的状态。其中:

西和网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设公司等网站项目制作,到程序开发,运营维护。创新互联公司2013年成立到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联。

DB_STARTUP:表示数据库正在启动状态,实际上没有使用该状态。

DB_SHUTDOWNED:数据库实例正常关闭(非standby)控制文件写入的状态就是这个状态

DB_SHUTDOWNED_IN_RECOVERY:standby实例正常关闭,控制文件写入的状态是这个状态。是由CreateRestartPoint修改该状态。

DB_SHUTDOWNING:非standby实例在关闭时,做checkpoint:CreateCheckPoint,开始做时修改为该状态,做完后修改为DB_SHUTDOWNED状态。

DB_IN_CRASH_RECOVERY:实例异常关闭,重启后,恢复时需要将实例先置为该状态

DB_IN_ARCHIVE_RECOVERY:standby实例重启后置为该状态。

DB_IN_PRODUCTION:非standby实例正常重启后就是这个状态,standby是DB_IN_ARCHIVE_RECOVERY

分析

1、DB_STARTUP

initdb->BootStrapXLOG:
	memset(ControlFile, 0, sizeof(ControlFileData));
	...
	ControlFile->state = DB_SHUTDOWNED;
	...
	WriteControlFile();

初始化时,首先将其状态初始化为DB_STARTUP,然后立即置成DB_SHUTDOWNED并将其刷写到磁盘。

2、StartupXLOG

StartupXLOG->
	ReadControlFile();
	...
	readRecoveryCommandFile();->
	|--...
	|	for (item = head; item; item = item->next){
	|		if (strcmp(item->name, "restore_command") == 0){
	|			...
	|		}...
	|		else if (strcmp(item->name, "standby_mode") == 0){
	|			if (!parse_bool(item->value, &StandbyModeRequested))
	|		}...
	|	}
	|	...
	|--	ArchiveRecoveryRequested = true;
	...
	if (ArchiveRecoveryRequested &&
			(ControlFile->minRecoveryPoint != InvalidXLogRecPtr ||
			 ControlFile->backupEndRequired ||
			 ControlFile->backupEndPoint != InvalidXLogRecPtr ||
			 ControlFile->state == DB_SHUTDOWNED)){
			InArchiveRecovery = true;
			if (StandbyModeRequested)
				StandbyMode = true;
	}
	...
	record = ReadCheckpointRecord(xlogreader, checkPointLoc, 1, true);
	...
	if (InRecovery){
		if (InArchiveRecovery)//何时?
			ControlFile->state = DB_IN_ARCHIVE_RECOVERY;
		else
			ControlFile->state = DB_IN_CRASH_RECOVERY;
		...
		UpdateControlFile();
		replay...
	}
	...
	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
	ControlFile->state = DB_IN_PRODUCTION;
	UpdateControlFile();
	LWLockRelease(ControlFileLock);
	...

只要有recovery.conf文件,ArchiveRecoveryRequested即为TRUE->InArchiveRecovery = true,配置了standby_mode=on,那么StandbyMode=TRUE。这样standby启动后,ControlFile->state为DB_IN_ARCHIVE_RECOVERY状态。

3、checkpoint

CheckpointerMain->
	for (;;){
		...
		if (shutdown_requested){
			ShutdownXLOG(0, 0);->
			|--if (RecoveryInProgress()){
			|	    CreateRestartPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
			|  }else{
			|	    CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
			|  }
			|--...
			proc_exit(0);
		}
		...
		if (do_checkpoint){
			do_restartpoint = RecoveryInProgress();
			...
			if (flags & CHECKPOINT_END_OF_RECOVERY)//flags从哪来?
				do_restartpoint = false;
			...
			if (!do_restartpoint){
				CreateCheckPoint(flags);
				ckpt_performed = true;
			}
			else
				ckpt_performed = CreateRestartPoint(flags);
		}
	}

备机上做checkpoint调用CreateRestartPoint,主机做checkpoint调用CreateCheckPoint

CreateCheckPoint(int flags)->
	if (flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY))
		shutdown = true;
	else
		shutdown = false;
	...
	if (shutdown){
		LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
		ControlFile->state = DB_SHUTDOWNING;
		ControlFile->time = (pg_time_t) time(NULL);
		UpdateControlFile();
		LWLockRelease(ControlFileLock);
	}
	...
	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
	if (shutdown)
		ControlFile->state = DB_SHUTDOWNED;
	...
	UpdateControlFile();
	LWLockRelease(ControlFileLock);

shutdown时,先将状态置为DB_SHUTDOWNING,最后将状态置为DB_SHUTDOWNED

CreateRestartPoint(int flags)->
	LWLockAcquire(CheckpointLock, LW_EXCLUSIVE);
	SpinLockAcquire(&XLogCtl->info_lck);
	lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
	lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
	lastCheckPoint = XLogCtl->lastCheckPoint;
	SpinLockRelease(&XLogCtl->info_lck);
	if (!RecoveryInProgress()){
		LWLockRelease(CheckpointLock);
		return false;
	}
	...
	if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||lastCheckPoint.redo <= ControlFile->checkPointCopy.redo){
		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;
	}
	...
	LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
	if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY && ControlFile->checkPointCopy.redo < lastCheckPoint.redo){
		...
		if (flags & CHECKPOINT_IS_SHUTDOWN)
			ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY;
		UpdateControlFile();
	}
	LWLockRelease(ControlFileLock);
	...

备机shutdown,将状态置为DB_SHUTDOWNED_IN_RECOVERY


文章题目:PostgreSQL状态变迁
分享链接:http://ybzwz.com/article/jsgdig.html