PostgreSQL状态变迁
admin
2023-05-20 22:03:05
0
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的状态。其中:

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


相关内容

热门资讯

缅甸发生5.2级地震,震源深度... 中国地震台网正式测定:05月18日10时05分在缅甸(北纬16.55度,东经96.25度)发生5.2...
大学校门如何正确地开放 武汉大学校门开放后的第一个周末,情况如我的预期。如部分游客存在爬树拍照打卡、在操场直播学生上体育课等...
文科改名潮:加了“智能”二字,... 过去几年里,“文科无用”“文科就业难”的讨论不断发酵。高校文科专业的变动也频繁且剧烈,据教育部数据,...
赛力斯申请多轴机器人运动轨迹校... 国家知识产权局信息显示,重庆赛力斯凤凰智创科技有限公司申请一项名为“多轴机器人运动轨迹校验方法、装置...
电信运营商开始卖Token,估... 2026年5月17日,中国电信正式推出了全国层面的试商用Token套餐,这标志着运营商的计费模式正从...
史上最大IPO,谁最躺赢? 今年科技IPO的热闹程度是空前的。 Cerebras刚刚在5月14日率先登场,发行价185美元,首日...
当“确定性”出现裂缝:迪拜的枢... 战争降临照片上是一幢写字楼,黑烟正从某一层往外冒,有几层的玻璃窗被完全击碎,窗框还挂着锯齿形的边角—...
视频丨“一部手机走天下” 中国... 从一线城市商圈到县域小店,从夜市摊贩到景区门票,在我们的日常生活中,二维码无处不在,移动支付普及率已...
2026世界电信和信息社会日报... 央广网南宁5月16日消息(记者梁瑜琳)在世界电信和信息社会日即将到来之际,5月15日,2026世界电...
当第一批丁克住进医院,关键时刻... 子女作为父母生命的延续和资源的继承者,自然该承担起养老的重担。而没有子女者住进医院,手术签字、术后付...