dram.me

Postgres95连接数据库流程

Postgres95的客户端psql主要在以下两点需要连接数据库:

  1. 启动命令时,通过命令行参数或环境变量指定数据库服务器主机和端口,以及数据库名称;

  2. 执行\c命令切换数据库时,需要重连服务。

\c命令在实现上和第一次连接数据库相同,在无法连接到新数据库时,会回退到先前的数据库。所以以上两个流程基本相同,最为核心的代码在interfaces/libpq/fe-connect.c文件中的PQsetdbconnectDB函数实现。

PQsetdb通过参数或者环境变量获取主机、端口、参数、数据库名称信息,初始化PGconn结构体实例,之后调用connectDB连接数据库。这里有一个细节,数据库名称可以作为参数直接指定,或者通过环境变量PGDATABASE指定,如果两者都没有指定,PG95会尝试获取用户名作为数据库名,用户名作为数据库名这一模式一直沿用至今,详见文档。而用户名的获取会在下面详细描述。

刚才提到,PG95在获取数据库名称时可能会用到用户名,而在connectDB连接数据库时,也需要指定。在PG95 1.01版本中,无法通过psql命令行指定用户名,另外也没有对应的PGUSER环境变量。用户名是基于Kerberos的credential cache获取的。如果无法获取,则会使用当前登录用户(通过getpwuid()获取)。之后就是惯常的TCP连接建立,以及通过startup2PacketBuf组装请求数据包,并通过packetSend发送。

另外有一个细节,在这里提一下,在startup2PacketBufpacketSend的注释中有提到,这两段代码与backend/libpq的代码类似,只是为了不链接libpq.a而在这边定义了。为何同时存在两份libpq代码(分别在backend和interfaces目录)?

从目录中文件命名来看,fe表示frontend,be表示backend。从内容上看,分别是客户端逻辑和服务端逻辑代码,这一点比较认证相关的代码就可以看出。

从Makefile看,最终的libpq库应该是由interfaces目录中的代码生成的,那backend目录中的libpq的意图是什么呢?主要是给PG内部使用的吗?这还需要进一步确认,特别是注释中提到的不链接libpq.a令人费解。