初步学习pg_control文件之二
接前文:初步认识pg_control文件
继续学习,pg_control文件在何处形成的?是在initdb的时候,运用的函数如下:
/* * This func must be called ONCE on system install. It creates pg_control * and the initial XLOG segment. */ void BootStrapXLOG(void) { CheckPoint checkPoint; char *buffer; XLogPageHeader page; XLogLongPageHeader longpage; XLogRecord *record; bool use_existent; uint64 sysidentifier; struct timeval tv; pg_crc32 crc; /* * Select a hopefully-unique system identifier code for this installation. * We use the result of gettimeofday(), including the fractional seconds * field, as being about as unique as we can easily get. (Think not to * use random(), since it hasn't been seeded and there's no portable way * to seed it other than the system clock value...) The upper half of the * uint64 value is just the tv_sec part, while the lower half is the XOR * of tv_sec and tv_usec. This is to ensure that we don't lose uniqueness * unnecessarily if "uint64" is really only 32 bits wide. A person * knowing this encoding can determine the initialization time of the * installation, which could perhaps be useful sometimes. */ gettimeofday(&tv, NULL); sysidentifier = ((uint64) tv.tv_sec) << 32; sysidentifier |= (uint32) (tv.tv_sec | tv.tv_usec); ... /* Now create pg_control */ memset(ControlFile, 0, sizeof(ControlFileData)); /* Initialize pg_control status fields */ ControlFile->system_identifier = sysidentifier; ControlFile->state = DB_SHUTDOWNED; ControlFile->time = checkPoint.time; ControlFile->checkPoint = checkPoint.redo; ControlFile->checkPointCopy = checkPoint; /* Set important parameter values for use when replaying WAL */ ControlFile->MaxConnections = MaxConnections; ControlFile->max_prepared_xacts = max_prepared_xacts; ControlFile->max_locks_per_xact = max_locks_per_xact; ControlFile->wal_level = wal_level; /* some additional ControlFile fields are set in WriteControlFile() */ WriteControlFile(); /* Bootstrap the commit log, too */ BootStrapCLOG(); BootStrapSUBTRANS(); BootStrapMultiXact(); pfree(buffer); }
说起来
system_identifier 这个东西 ,是随机算出来的一个值:
/* * Select a hopefully-unique system identifier code for this installation. * We use the result of gettimeofday(), including the fractional seconds * field, as being about as unique as we can easily get. (Think not to * use random(), since it hasn't been seeded and there's no portable way * to seed it other than the system clock value...) The upper half of the * uint64 value is just the tv_sec part, while the lower half is the XOR * of tv_sec and tv_usec. This is to ensure that we don't lose uniqueness * unnecessarily if "uint64" is really only 32 bits wide. A person * knowing this encoding can determine the initialization time of the * installation, which could perhaps be useful sometimes. */ gettimeofday(&tv, NULL); sysidentifier = ((uint64) tv.tv_sec) << 32; sysidentifier |= (uint32) (tv.tv_sec | tv.tv_usec); ... ControlFile->system_identifier = sysidentifier;
state 在初始化的时候,是有SHUTDOWNED。另外可能的值也都可以在pg_control.h中看到:
/* * System status indicator. Note this is stored in pg_control; if you change * it, you must bump PG_CONTROL_VERSION */ 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;
这几个值何时用,状态如何变化,应该是一个很有意思的话题。