PostgreSQL服务过程中的那些事一:启动postgres服务进程一.八:
话说调用 InitPostgres 方法给portgres服务进程做相关初始化,这个方法里初始化了relcache和catcache,初始化了执行查询计划的portal的管理器,填充本进程PGPROC结构相关部分成员等,上一节讨论了portal管理环境的初始化,这一节继续讨论剩余的相关初始化。
话说调用InitPostgres方法给portgres服务进程做相关初始化,这个方法里初始化了relcache和catcache,初始化了执行查询计划的portal的管理器,填充本进程PGPROC结构相关部分成员等,上一节讨论了portal管理环境的初始化,这一节继续讨论剩余的相关初始化。
1
先看InitPostgres方法的调用序列梗概图
InitPostgres方法的调用序列梗概图
InitPostgres方法为初始化这个postgres服务进程做了一系列的工作,具体如下:
(1)调用InitProcessPhase2方法,把本进程的PGPROC结构注册到PGPROC数组,就是让共享内存里的PGPROC数组(初始化PGPROC数组的文章见《PostgreSQL启动过程中的那些事七:初始化共享内存和信号十一:shmem中初始化SharedProcArray》)的第一个空元素指向这个PGPROC结构,并注册退出时做内存清理的函数。
(2)调用SharedInvalBackendInit方法,在该后台进程数据的共享失效管理器数组获取一个ProcState结构(相关数据结果见《PostgreSQL启动过程中的那些事七:初始化共享内存和信号十三:shmem中初始化SharedInvalidationState》)给该进程并初始化相关项,并注册退出方法以在退出时标记本进程的项非活跃。
(3)调用ProcSignalInit方法,在ProcSignalSlot结构数组(关于ProcSignalSlot结构数组参见《PostgreSQL启动过程中的那些事七:初始化共享内存和信号十四:shmem中初始化PMSignal》)ProcSignalSlots里给当前进程获取一个元素,元素下标是MyBackendId-1,并注册以在进程退出时释放这个槽。
(4)为访问XLOG,调用RecoveryInProgress方法做共享内存相关初始化。
(5)调用RelationCacheInitlisze方法做管理relcache的环境的初始化。
(6)调用InitCatalogCache方法做管理catcache的环境的初始化。
(7)调用EnablePortalManager方法初始化portal管理器。
(8)调用RelationCacheInitializePhase2方法初始化共享系统表。
(9)调用GetTransactionSnapshot方法获取一个事务快照。这个方法在后面讨论简单查询时再讨论。
(10)调用PerformAuthentication方法根据hba文件设置进行客户端认证。
(11)调用GetDatabaseTuple方法根据数据库名字从pg_database系统表获取要访问的数据库对应的元组。
(12)调用RelationCacheInitializePhase3方法完成relcache初始化。
(13)调用CheckMyDatabase方法检查当前用户的数据库访问权限,从cache里的pg_database取当前数据库的相关属性字段。
(14)调用InitializeClientEncoding方法初始化客户端字符编码。
(15)调用pgstat_bestart方法在PgBackendStatus设置本进程状态。
2
这一节概论第8步到第15步。先看一下后续方法的调用序列图,为了图能大一点,PostgresMain以前的调用流程序列就从下面的图中省略了,要回顾可以参考上面的“InitPostgres方法的调用序列梗概图”。
相关方法调用序列图
下面讨论第(8)步,RelationCacheInitializePhase2方法初始化共享catalog。先看一下为什么要有第(5)、(8)、(12)步三步来初始化relcache。当前还处在数据库服务器和客户端建立连接的过程中,数据库服务器的服务进程要根据连接串中指定数据库加载其相关对象,但此时服务器端还没有加载访问数据库的基础设施,比如系统表"pg_database"、"pg_authid"、"pg_auth_members"等的描述符及其相关索引信息,因此无法通过系统表访问数据库的相关信息。第(5)步初始化relcache的管理环境,参见《
PostgreSQL服务过程中的那些事一:启动postgres服务进程一.五:初始化relcache管理环境
》。第(8)步通过"global/pg_filenode.map"、"global/pg_internal.init"文件初始化共享catalog:"pg_catalog",将系统表"pg_database"、"pg_authid"、"pg_auth_members"等的描述符信息加载到relcache里。"global/pg_filenode.map"文件里存放的是数据库中关系和文件节点的映射信息,"global/pg_internal.init"文件里存放的是"pg_class"、"pg_attribute"、"pg_proc"、"pg_type"等系统关系信息。然后完成设置数据库快照(第9步)、根据hba文件完成客户端认证(第10步)、从pg_database获取客户端要访问的数据库的对应元组(第11步),第(12)步根据要访问的数据库ID,加载该数据库本地的"pg_filenode.map"、"pg_internal.init"文件完成初始化。加载"pg_class"、"pg_attribute"、"pg_proc"、"pg_type"等及其索引信息。如果从相关"pg_filenode.map"、"pg_internal.init"文件初始化失败,系统会从硬编码的代码中初始化基础设施相关关系信息,下面摘录了"pg_database"、"pg_authid"、"pg_auth_members"的硬编码信息。不管加载那个文件,完成相关信息初始化后如有必要将重新该文件。重写时先写临时文件,写完后改文件名为正式文件。这样做是为了避免并发的后台进程读相关文件时崩溃。关于文件名举个例子,例如文件"data/global/pg_internal.init",对应的临时文件名是"data/global/pg_internal.init.pid",最后的"pid"是当前进程ID。第(13)步调用CheckMyDatabase方法检查当前用户的数据库访问权限,从cache里的pg_database取当前数据库的相关属性字段。第(14)调用InitializeClientEncoding方法初始化客户端字符编码。第(15)调用pgstat_bestart方法在PgBackendStatus设置本进程状态。至此pg服务进程的初始化工作告一段落。
下面是部分系统关系硬编码信息:
DATA(insert OID = 11 ( "pg_catalog" PGUID _null_ ));
DESCR("system catalog schema");
#define PG_CATALOG_NAMESPACE11
#define DatabaseRelationId 1262
#define DatabaseRelation_Rowtype_Id 1248
CATALOG(pg_database,1262)BKI_SHARED_RELATION BKI_ROWTYPE_OID(1248) BKI_SCHEMA_MACRO
{
NameData datname; /* database name */
Oid datdba; /* owner of database */
int4 encoding; /* character encoding */
NameData datcollate; /* LC_COLLATE setting */
NameData datctype; /* LC_CTYPE setting */
bool datistemplate; /* allowed as CREATE DATABASE template? */
bool datallowconn; /* new connections allowed? */
int4 datconnlimit; /* max connections allowed (-1=no limit) */
Oid datlastsysoid; /* highest OID to consider a system OID */
TransactionId datfrozenxid; /* all Xids
Oid dattablespace; /* default table space for this DB */
aclitem datacl[1]; /* access permissions (VAR LENGTH) */
} FormData_pg_database;
/* ----------------
* Form_pg_databasecorresponds to a pointer to a tuple with
* theformat of pg_database relation.
* ----------------
*/
typedef FormData_pg_database *Form_pg_database;
/* ----------------
* pg_authiddefinition. cpp turns this into
* typedefstruct FormData_pg_authid
* ----------------
*/
#define AuthIdRelationId 1260
#define AuthIdRelation_Rowtype_Id 2842
CATALOG(pg_authid,1260)BKI_SHARED_RELATION BKI_ROWTYPE_OID(2842) BKI_SCHEMA_MACRO
{
NameData rolname; /* name of role */
bool rolsuper; /* read this field via superuser() only! */
bool rolinherit; /* inherit privileges from other roles? */
bool rolcreaterole; /* allowed to create more roles? */
bool rolcreatedb; /* allowed to create databases? */
bool rolcatupdate; /* allowed to alter catalogs manually? */
bool rolcanlogin; /* allowed to log in as session user? */
bool rolreplication; /* role used for streaming replication */
int4 rolconnlimit; /* max connections allowed (-1=no limit) */
/* remaining fields may be null; use heap_getattr to read them! */
text rolpassword; /* password, if any */
timestamptz rolvaliduntil; /* password expiration time, if any */
} FormData_pg_authid;
#undef timestamptz
/* ----------------
* Form_pg_authidcorresponds to a pointer to a tuple with
* theformat of pg_authid relation.
* ----------------
*/
typedef FormData_pg_authid *Form_pg_authid;
/* ----------------
* pg_auth_membersdefinition. cpp turns this into
* typedefstruct FormData_pg_auth_members
* ----------------
*/
#define AuthMemRelationId 1261
#define AuthMemRelation_Rowtype_Id 2843
CATALOG(pg_auth_members,1261)BKI_SHARED_RELATION BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(2843) BKI_SCHEMA_MACRO
{
Oid roleid; /* ID of a role */
Oid member; /* ID of a member of that role */
Oid grantor; /* who granted the membership */
bool admin_option; /* granted with admin option? */
} FormData_pg_auth_members;
/* ----------------
* Form_pg_auth_memberscorresponds to a pointer to a tuple with
* theformat of pg_auth_members relation.
* ----------------
*/
typedef FormData_pg_auth_members *Form_pg_auth_members;
就到这儿吧!
------------
blog.csdn.net/beiigang
beigang.iteye.com