Table of Contents
COPY命令相关的函数libpq是应用程序员使用PostgreSQL的C接口。libpq是一个库函数的集合,它们允许客户端程序传递查询给PostgreSQL后端服务器并且接收这些查询的结果。
libpq也是很多其他PostgreSQL应用接口的底层引擎,包括为 C++、Perl、Python、Tcl 和 ECPG编写的接口。如果你使用那些包,某些方面的libpq行为将会对你很重要。特别是,Section 32.15、Section 32.16和Section 32.19描述了任何使用libpq的应用的用户可见的行为。
在本章的末尾(Section 32.23)包括了一些短程序来展示如何编写使用libpq的应用。在源代码发布的src/test/examples目录中还有一些完整的libpq应用的示例。
使用libpq的客户端程序必须包括头文件libpq-fe.h并必须与libpq库链接在一起。
下列函数会建立到一个PostgreSQL后端服务器的连接。 一个应用程序可以在一个时刻打开多个后端连接(原因之一就是为了访问多个数据库)。 每个连接用一个PGconn对象表示,它从函数PQconnectdb、PQconnectdbParams,或PQsetdbLogin得到。 注意这些函数将总是返回一个非空的对象指针,除非正好没有内存来分配PGconn对象。 在通过该连接对象发送查询之前,应该调用PQstatus函数来检查返回值以确定是否得到了一个成功的连接。
如果不可信用户能够访问一个没有采用安全的模式使用模式的数据库,那么每个会话开始时都应从search_path中移除公开可写的模式。可以把参数关键词options设置为-csearch_path=。也可以在连接后发出PQexec(。这种考虑并非专门针对libpq;它适用于每一种可执行任意 SQL 命令的接口。conn, "SELECT pg_catalog.set_config('search_path', '', false)")
在 Unix 上,复制一个拥有打开 libpq 连接的进程可能导致不可预料的结果,因为父进程和子进程会共享相同的套接字和操作系统资源。出于这个原因,我们不推荐这样的用法,尽管从子进程执行一个exec来载入新的可执行代码是安全的。
PQconnectdbParams #开启一个到数据库服务器的新连接。
PGconn *PQconnectdbParams(const char * const *keywords,
const char * const *values,
int expand_dbname);
这个函数使用从两个以NULL结尾的数组中取得的参数打开一个新的数据库连接。第一个数组keywords是一个字符串数组,其中每个元素都是一个关键词。第二个数组values给出每个关键词的值。和下面的PQsetdbLogin不同,参数集合可以在不改变函数签名的情况下扩展,因此对于新应用,最好使用这个函数(或者相应的非阻塞函数PQconnectStartParams和PQconnectPoll)。
当前能被识别的参数关键词被列举在Section 32.1.2中。
被传递的数组可以为空,这样就会使用所有默认参数。 也可以只包含一个或几个参数设置。他们在长度上必须匹配。 对于参数数组的处理将会停止于keywords数组中第一个NULL元素。 而且,如果与非-NULL keywords条目相关联的values条目为NULL或者空字符串,则忽略该项并继续处理下一对数组项。
当expand_dbname为非零时,会检查第一个dbname关键词的值以查看它是否为一个连接字符串。 如果是,它被“扩展”到从字符串中提取的单独的连接参数。 该值被认为是一个连接字符串,而不仅是一个数据库名称,如果它包含一个等号(=)或者它以URI模式标志符开头, (有关连接字符串格式的更多详情可见Section 32.1.1。) 只有dbname的第一次出现会按这种方式处理,任何后续dbname值会被当做一个普通数据库名处理。
通常,参数数组从开头到结尾进行处理。 当关键词有重复时,使用最后一个值(不是 NULL 或空)。 此规则特别适用于连接字符串中的关键字与一个出现在keywords数组中的关键字冲突的情况。 因此,程序员可以决定数组条目是否能被覆盖或用连接字符串获取的值覆盖。 出现在扩展的dbname条目之前的数组条目可以被连接字符串的字段所覆盖,反之,这些字段被dbname之后出现的数组条目所覆盖。(但是,再有,只有在那些条目支持非空值时。)
在处理完所有数组条目和任何扩展的连接字符串后,所有未设置的连接参数都将使用默认值填充。 如果一个未设置参数的相关环境变量(参见 Section 32.15)被设置了,它的值会被使用。 如果环境变量未被设置,则使用参数的内置默认值。
PQconnectdb #开启一个到数据库服务器的新连接。
PGconn *PQconnectdb(const char *conninfo);
这个函数使用从字符串conninfo中得到的参数开启一个新的数据库连接。
被传递的字符串可以为空,这样将会使用所有的默认参数。也可以包含由空格分隔的一个或多个参数设置,还可以包含一个URI。详见Section 32.1.1。
PQsetdbLogin #开启一个到数据库服务器的新连接。
PGconn *PQsetdbLogin(const char *pghost,
const char *pgport,
const char *pgoptions,
const char *pgtty,
const char *dbName,
const char *login,
const char *pwd);
这是PQconnectdb的带有固定参数集合的前辈。它具有相同的功能,不过其中缺失的参数将总是采用默认值。对任意一个固定参数写NULL或一个空字符串将会使它采用默认值。
如果dbName包含一个=符号或者具有一个合法的连接URI前缀,它会被当作一个conninfo字符串,就好像它已经被传递给了PQconnectdb,并且剩余的参数则被应用为指定给PQconnectdbParams。
pgtty 已经不再使用,任何传递的值将被忽略。
PQsetdb #开启一个到数据库服务器的新连接。
PGconn *PQsetdb(char *pghost,
char *pgport,
char *pgoptions,
char *pgtty,
char *dbName);
这是一个调用PQsetdbLogin的宏,其中为login和pwd参数使用空指针。提供它是为了向后兼容非常老的程序。
PQconnectStartParamsPQconnectStartPQconnectPoll #
PGconn *PQconnectStartParams(const char * const *keywords,
const char * const *values,
int expand_dbname);
PGconn *PQconnectStart(const char *conninfo);
PostgresPollingStatusType PQconnectPoll(PGconn *conn);
这三个函数被用来开启一个到数据库服务器的连接,这样你的应用的执行线程不会因为远程的I/O而被阻塞。这种方法的要点在于等待 I/O 完成可能在应用的主循环中发生,而不是在PQconnectdbParams 或 PQconnectdb中,并且因此应用能够把这种操作和其他动作并行处理。
在PQconnectStartParams中,数据库连接使用从keywords和values数组中取得的参数创建,并且被expand_dbname控制,这和之前描述的PQconnectdbParams相同。
在PQconnectStart中,数据库连接使用从字符串conninfo中取得的参数创建,这和之前描述的PQconnectdb相同。
只要满足一些限制,PQconnectStartParams或PQconnectStart或PQconnectPoll都不会阻塞:
hostaddr和host参数必须被合适地使用,以防止做DNS查询。详见Section 32.1.2中这些参数的文档。
如果你调用PQtrace,确保你追踪的该流对象不会阻塞。
如后文所述,你必须要确保在调用PQconnectPoll之前,套接字处于合适的状态。
要开始无阻塞的连接请求,可调用PQconnectStart或者PQconnectStartParams。如果结果为空,则libpq无法分配一个新的PGconn结构。否则,一个有效的PGconn指针会被返回(不过还没有表示一个到数据库的有效连接)。接下来调用PQstatus(conn)。如果结果是CONNECTION_BAD,则连接尝试已经失败,通常是因为有无效的连接参数。
如果PQconnectStart或PQconnectStartParams成功,下一个阶段是轮询libpq,这样它能够继续进行连接序列。使用PQsocket(conn)来获得该数据库连接底层的套接字描述符(警告:不要假定在PQconnectPoll调用之间套接字会保持相同)。这样循环:如果PQconnectPoll(conn)上一次返回PGRES_POLLING_READING,等到该套接字准备好读取(按照select()、poll()或类似的系统函数所指示的)。则再次调用PQconnectPoll(conn)。反之,如果PQconnectPoll(conn)上一次返回PGRES_POLLING_WRITING,等到该套接字准备好写入,则再次调用PQconnectPoll(conn)。在第一次迭代时,即如果你还没有调用PQconnectPoll,行为就像是它上次返回了PGRES_POLLING_WRITING。持续这个循环直到PQconnectPoll(conn)返回PGRES_POLLING_FAILED指示连接过程已经失败,或者返回PGRES_POLLING_OK指示连接已经被成功地建立。
在连接期间的任意时刻,该连接的状态可以通过调用PQstatus来检查。如果这个调用返回CONNECTION_BAD,那么连接过程已经失败。如果该调用返回CONNECTION_OK,则该连接已经准备好。如前所述,这些状态同样都可以从PQconnectPoll的返回值检测。在一个异步连接过程中(也只有在这个过程中)也可能出现其他状态。这些状态指示该连接过程的当前阶段,并且可能有助于为用户提供反馈。这些状态是:
注意,尽管这些常数将被保留(为了维护兼容性),一个应用永远不应该依赖这些状态按照特定顺序出现,或者根本就不依赖它们,或者不依赖状态总是这些文档中所说的值。一个应用可能做些这样的事情:
switch(PQstatus(conn))
{
case CONNECTION_STARTED:
feedback = "Connecting...";
break;
case CONNECTION_MADE:
feedback = "Connected to server...";
break;
.
.
.
default:
feedback = "Connecting...";
}
在使用PQconnectPoll时,连接参数connect_timeout会被忽略:判断是否超时是应用的责任。否则,PQconnectStart后面跟着PQconnectPoll循环等效于PQconnectdb。
注意当PQconnectStart或PQconnectStartParams返回一个非空的指针时,你必须在用完它之后调用PQfinish来处理那些结构和任何相关的内存块。即使连接尝试失败或被放弃时也必须完成这些工作。
PQconndefaults #返回默认连接选项。
PQconninfoOption *PQconndefaults(void);
typedef struct
{
char *keyword; /* 该选项的关键词 */
char *envvar; /* 依赖的环境变量名 */
char *compiled; /* 依赖的内置默认值 */
char *val; /* 选项的当前值,或者 NULL */
char *label; /* 连接对话框中域的标签 */
char *dispchar; /* 指示如何在一个连接对话框中显示这个域。值是:
"" 显示输入的值
"*" 密码域 - 隐藏值
"D" 调试选项 - 默认不显示 */
int dispsize; /* 用于对话框的以字符计的域尺寸 */
} PQconninfoOption;
返回一个连接选项数组。这可以用来确定用于连接服务器的所有可能的PQconnectdb选项和它们的当前缺省值。返回值指向一个PQconninfoOption结构的数组,该数组以一个包含空keyword指针的条目结束。如果无法分配内存,则返回该空指针。注意当前缺省值(val域)将依赖于环境变量和其他上下文。一个缺失或者无效的服务文件将会被无声地忽略掉。调用者必须把连接选项当作只读对待。
在处理完选项数组后,把它交给PQconninfoFree释放。如果没有这么做, 每次调用PQconndefaults都会导致一小部分内存泄漏。
PQconninfo #返回被一个活动连接使用的连接选项。
PQconninfoOption *PQconninfo(PGconn *conn);
返回一个连接选项数组。这可以用来确定用于连接服务器的所有可能的PQconnectdb选项和它们的当前缺省值。 返回值指向一个PQconninfoOption结构的数组,该数组以一个包含空keyword指针的条目结束。 上述所有对于PQconndefaults的注解也适用于PQconninfo的结果。
PQconninfoParse #返回从提供的连接字符串中解析到的连接选项。
PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg);
解析一个连接字符串并且将结果选项作为一个数组返回,或者在连接字符串有问题时返回NULL。这个函数可以用来抽取所提供的连接字符串中的PQconnectdb选项。返回值指向一个PQconninfoOption结构的数组,该数组以一个包含空keyword指针的条目结束。
所有合法选项将出现在结果数组中,但是任何在连接字符串中没有出现的选项的PQconninfoOption的val会被设置为NULL,默认值不会被插入。
如果errmsg不是NULL,那么成功时*errmsg会被设置为NULL, 否则设置为被malloc过的错误字符串以说明该问题(也可以将*errmsg设置为NULL并且函数返回NULL,这表示一种内存耗尽的情况)。
在处理完选项数组后,把它交给PQconninfoFree释放。如果没有这么做, 每次调用PQconninfoParse都会导致一小部分内存泄漏。反过来,如果发生一个错误并且errmsg不是NULL,确保使用PQfreemem释放错误字符串。
PQfinish #关闭与服务器的连接。同时释放PGconn对象使用的内存。
void PQfinish(PGconn *conn);
注意,即使与服务器的连接尝试失败(由PQstatus指示),应用也应当调用PQfinish来释放PGconn对象使用的内存。不能在调用PQfinish之后再使用PGconn指针。
PQreset #重置与服务器的通讯通道。
void PQreset(PGconn *conn);
此函数将关闭与服务器的连接,并尝试建立一个新连接,用之前使用过的所有参数。 这可能有助于在工作连接丢失后的错误恢复。
PQresetStartPQresetPoll #以非阻塞方式重置与服务器的通讯通道。
int PQresetStart(PGconn *conn); PostgresPollingStatusType PQresetPoll(PGconn *conn);
这些函数将关闭与服务器的连接,并且使用所有之前使用过的参数尝试建立一个新连接。 这可能有助于在工作连接丢失后的错误恢复。 它们和上面的PQreset的不同在于它们工作在非阻塞方式。 这些函数受到PQconnectStartParams、PQconnectStart和PQconnectPoll相同的限制。
要发起一次连接重置,调用PQresetStart。如果它返回 0,那么重置失败。如果返回 1,就按使用PQresetPoll建立连接时相同的方法,继续调用PQresetPoll来重置连接。
PQpingParams #PQpingParams报告服务器的状态。它接受与PQconnectdbParams相同的连接参数,如上所述。获得服务器状态不需要提供正确的用户名、密码或数据库名。不过,如果提供了不正确的值,服务器将记录一次失败的连接尝试。
PGPing PQpingParams(const char * const *keywords,
const char * const *values,
int expand_dbname);
该函数返回下列值之一:
PQping #PQping报告服务器的状态。它接受与PQconnectdb相同的连接参数。获得服务器状态不需要提供正确的用户名、密码或数据库名。不过,如果提供了不正确的值,服务器将记录一次失败的连接尝试。
PGPing PQping(const char *conninfo);
返回值和PQpingParams相同。
PQsetSSLKeyPassHook_OpenSSL #PQsetSSLKeyPassHook_OpenSSL允许应用覆盖libpq对加密客户端证书密钥文件的默认处理方式, 包括使用sslpassword或交互式提示输入密码的处理。
void PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook);
应用程序传入一个指向回调函数的指针,其签名为:
int callback_fn(char *buf, int size, PGconn *conn);
随后,libpq会调用该回调,而不是调用其默认的PQdefaultSSLKeyPassHook_OpenSSL处理程序。 回调函数应确定密钥密码,并将其复制到大小为size的结果缓冲区buf中。 buf中的字符串必须以空字符结尾。 回调函数必须返回存储在buf中的密码长度,不包括结尾的空字符。 如果失败,回调函数应设置buf[0] = '\0'并返回 0。 参见libpq源代码中的PQdefaultSSLKeyPassHook_OpenSSL以获得示例。
如果用户指定了一个显式的密钥位置,那么当调用回调时,它的路径将在conn->sslkey中。 如果使用默认密钥路径,则这将为空。 对于作为引擎说明符的密钥,由引擎实现决定它们是使用OpenSSL密码回调还是定义自己的处理方式。
应用回调可以选择把未处理的情况委派给PQdefaultSSLKeyPassHook_OpenSSL,也可以先调用它,如果它返回 0 再尝试其他方法,或者完全覆盖它。
除了异常、longjmp(...)等情况外,回调务必不可跳出正常控制流。它必须正常返回。
PQgetSSLKeyPassHook_OpenSSL #PQgetSSLKeyPassHook_OpenSSL返回当前客户端证书密钥密码钩子,如果没有设置则返回NULL。
PQsslKeyPassHook_OpenSSL_type PQgetSSLKeyPassHook_OpenSSL(void);
几个libpq函数解析用户指定的字符串以获取连接参数。 这些字符串有两种被接受的格式:普通的关键字/值字符串和URI。URI通常遵循 RFC 3986,除了允许多主机连接字符串,如下面进一步描述的那样。
在关键词/值格式中,每一个参数设置的形式都是关键词 = 值,在设置之间有空白。 设置的等号周围的空白是可选的。 要写一个空值或一个包含空白的值,将它用单引号包围,例如关键词 = 'a value'。 值里面的单引号和反斜线必须用一个反斜线转义,即\'和\\。
示例:
host=localhost port=5432 dbname=mydb connect_timeout=10
能被识别的参数关键词在Section 32.1.2中列出。
一个连接URI的一般形式是:
postgresql://[userspec@][hostspec][/dbname][?paramspec] whereuserspecis:user[:password] andhostspecis: [host][:port][,...] andparamspecis:name=value[&...]
URI模式标志符可以是postgresql://或postgres://。 每一个剩下的URI部分都是可选的。 下列示例展示了合法的URI语法:
postgresql:// postgresql://localhost postgresql://localhost:5433 postgresql://localhost/mydb postgresql://user@localhost postgresql://user:secret@localhost postgresql://other@localhost/otherdb?connect_timeout=10&application_name=myapp postgresql://host1:123,host2:456/somedb?target_session_attrs=any&application_name=myapp
通常出现在URI的层次部分的值,也能够以命名参数的方式给出。例如:
postgresql:///mydb?host=localhost&port=5433
全部的命名参数必须匹配Section 32.1.2中列出的关键词,除了与JDBC连接URI兼容之外,ssl=true的实例转换到sslmode=require。
连接URI需要使用百分号编码 对其进行编码,如果其中包含具有特殊含义的符号。这里是一个示例,其中等号(=)被替换为 %3D,空格字符被替换为 %20:
postgresql://user@localhost:5433/mydb?options=-c%20synchronous_commit%3Doff
主机部分可能是主机名或一个 IP 地址。要指定一个 IPv6 地址,将它封闭在方括号中:
postgresql://[2001:db8::1234]/database
主机组件会被按照参数host对应的描述来解释。 特别地,如果主机部分是空或看起来像一个绝对路径名称,将使用一个 Unix 域套接字连接,否则将启动一个 TCP/IP 连接。 不过要注意,斜线是 URI 层次部分中的一个保留字符。 因此,要指定一个非标准的 Unix 域套接字目录,要么忽略 URI 中的主机部分并且指定该主机为一个命名参数,要么在 URI 的主机部分用百分号编码路径:
postgresql:///dbname?host=/var/lib/postgresql postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
可以在一个URI中指定多个主机,每一个都有一个可选的端口。 一个形式为postgresql://host1:port1,host2:port2,host3:port3/的URI等效于host=host1,host2,host3 port=port1,port2,port3形式的连接字符串。 如下所述,每一个主机都将被尝试,直到成功地建立一个连接。
可以指定多个要连接的主机,这样它们会按给定的顺序被尝试。 在键/值格式中,host、hostaddr和port选项都接受逗号分隔的值列表。 在指定的每一个选项中都必须给出相同数量的元素,这样第一个hostaddr对应于第一个主机名,第二个hostaddr对应于第二个主机名,以此类推。 不过,如果仅指定一个port,它将被应用于所有的主机。
在连接URI格式中,在URI的host部分我们可以列出多个由逗号分隔的host:port对。
不管是哪一种格式,单一的主机名可以被翻译成多个网络地址。常见的示例是一个主机同时具有IPv4和IPv6地址。
当多个主机被指定时或者单个主机名被翻译成多个地址时,所有的主机和地址都将按照顺序被尝试,直至遇到一个成功的。如果没有主机可以到达,则连接失败。如果成功地建立一个连接但是认证失败,也不会尝试列表中剩下的主机。
如果使用了密码文件,可以为不同的主机使用不同的密码。所有其他连接选项对列表中的每一台主机都是相同的,例如不能为不同的主机指定不同的用户名。
目前被识别的参数关键字包括:
host #要连接的主机名。如果主机名看起来像绝对路径名, 则指定的是Unix域通信而不是TCP/IP通信;该值是存储套接字文件的目录的名称。 (在Unix上,绝对路径名以斜杠开头。在Windows上,以驱动器号开头的路径也被识别。) 如果主机名以@开头,则将其视为抽象命名空间中的Unix域套接字(目前在Linux和Windows上支持)。 当未指定host或为空时,默认行为是连接到Unix域套接字在 /tmp(或在构建PostgreSQL时指定的套接字目录)中。在Windows和 没有Unix域套接字的机器上,默认是连接到localhost。
也可以接受一个逗号分隔的主机名列表,此时列表中的每个主机名将按顺序尝试; 列表中的空项将选择上述默认行为。详细信息请参见Section 32.1.1.3。
hostaddr #要连接的主机的数字IP地址。这应该是标准的IPv4地址格式,例如,172.28.40.9。 如果您的机器支持IPv6,也可以使用这些地址。当为此参数指定非空字符串时,总是使用TCP/IP通信。 如果未指定此参数,则将查找host的值以查找相应的IP地址 — 或者,如果host指定了IP地址,则将直接使用该值。
使用hostaddr允许应用程序避免主机名查找,这在有时间限制的应用程序中可能很重要。 但是,对于GSSAPI或SSPI认证方法以及verify-full SSL证书验证,需要主机名。 使用以下规则:
如果指定了host而没有指定hostaddr,则会发生主机名查找。 (当使用PQconnectPoll时,查找发生在PQconnectPoll首次考虑此主机名时, 并且可能导致PQconnectPoll阻塞一段时间。)
如果指定了hostaddr而没有指定host, 则hostaddr的值给出服务器的网络地址。 如果认证方法需要主机名,则连接尝试将失败。
如果同时指定了host和hostaddr, 则hostaddr的值给出服务器的网络地址。 除非认证方法需要,否则host的值将被忽略, 在这种情况下,它将用作主机名。
请注意,如果host不是网络地址hostaddr上服务器的名称, 则认证可能会失败。 此外,当同时指定host和hostaddr时, host用于在密码文件中标识连接(请参阅Section 32.16)。
也可以接受一个逗号分隔的hostaddr值列表,此时将按顺序尝试列表中的每个主机。 列表中的空项会导致使用相应的主机名,如果主机名也为空,则使用默认主机名。详见 Section 32.1.1.3。
没有主机名或主机地址, libpq将使用本地的Unix域套接字进行连接; 或者在Windows和没有Unix域套接字的机器上,它将尝试连接到localhost。
port #连接到服务器主机的端口号,或者Unix域连接的套接字文件名扩展。 如果在host或hostaddr参数中给出了多个主机, 则此参数可以指定与主机列表长度相同的逗号分隔的端口列表,或者可以指定用于所有主机的单个端口号。 空字符串,或逗号分隔列表中的空项,指定了在构建PostgreSQL时建立的默认端口号。
dbname #数据库名称。默认为与用户名相同。在某些情况下,该值会被检查是否为扩展格式; 有关更多详细信息,请参阅Section 32.1.1。
user #PostgreSQL用户连接的用户名。 默认为运行应用程序的操作系统用户名相同。
password #如果服务器要求密码认证,则使用密码。
passfile #指定用于存储密码的文件名(参见Section 32.16)。 默认为~/.pgpass,或在Microsoft Windows上为%APPDATA%\postgresql\pgpass.conf。 (如果此文件不存在,则不会报告错误。)
require_auth #指定客户端要求服务器采用的认证方法。如果服务器没有使用所要求的方法来认证客户端,或者服务器没有完整完成认证握手,则连接将失败。也可以提供一个以逗号分隔的方法列表,此时服务器必须准确使用其中一种方法,连接才会成功。默认情况下接受任意认证方法,并且服务器也可以完全跳过认证。
可以在方法名前加上!前缀以表示否定,此时服务器不得尝试所列方法;除此之外,任何其他方法都可接受,并且服务器也可以完全不认证客户端。如果提供的是逗号分隔列表,服务器不得尝试其中任何一个被否定的方法。否定形式和非否定形式不能在同一设置中混用。
最后还有一种特殊情况:none方法要求服务器不使用认证质询。(它也可以被否定,用来要求必须进行某种认证。)
可指定的方法如下:
password服务器必须请求明文密码认证。
md5服务器必须请求 MD5 哈希密码认证。
对 MD5 加密密码的支持已被废弃,并将在未来的PostgreSQL版本中移除。关于迁移到其他密码类型的细节,请参见Section 20.5。
gss服务器必须通过GSSAPI请求 Kerberos 握手,或者建立一个经过GSS加密的通道(另见gssencmode)。
sspi服务器必须请求 Windows SSPI 认证。
scram-sha-256服务器必须与客户端成功完成一次 SCRAM-SHA-256 认证交换。
oauth服务器必须向客户端请求 OAuth Bearer 令牌。
none服务器不得提示客户端执行认证交换。(这并不禁止通过 TLS 进行客户端证书认证,也不禁止通过其加密传输进行 GSS 认证。)
channel_binding #这个选项控制客户端对通道绑定的使用。设置为require表示连接必须使用通道绑定, prefer表示客户端将在可用时选择通道绑定, 而disable则阻止使用通道绑定。默认情况下, 如果PostgreSQL是使用SSL支持编译的,则默认为prefer; 否则默认为disable。
通道绑定是服务器向客户端证明自身身份的一种方法。它只在使用PostgreSQL 11 或更高版本服务器、并采用SCRAM认证方法的 SSL 连接上受支持。
connect_timeout #连接时的最长等待时间,以秒为单位(写成十进制整数,例如,10)。 零、负值或未指定表示无限等待。最小允许的超时时间为2秒,因此 1的值被解释为2。 此超时时间分别适用于每个主机名或IP地址。 例如,如果指定了两个主机和connect_timeout 为5,如果在5秒内没有建立连接,每个主机将超时, 因此等待连接的总时间可能长达10秒。
client_encoding #这将为此连接设置client_encoding配置参数。除了对应服务器选项接受的值外, 您还可以使用auto来从客户端的当前区域设置(Unix系统上的LC_CTYPE环境变量)确定正确的编码。
options #指定连接开始时发送到服务器的命令行选项。例如,将其设置为-c geqo=off会把会话的geqo参数值设为off。 此字符串中的空格被视为分隔命令行参数,除非用反斜杠(\)转义;写\\表示字面上的反斜杠。 有关可用选项的详细讨论,请参阅Chapter 19。
application_name #指定application_name配置参数的值。
fallback_application_name #指定application_name配置参数的回退值。 如果没有通过连接参数或PGAPPNAME环境变量为application_name指定值, 则将使用此值。在通用实用程序中指定回退名称很有用,该程序希望设置默认应用程序名称, 但允许用户覆盖它。
keepalives #控制是否使用客户端TCP保持活动。默认值为1,表示开启,但如果不想要保持活动,可以将其更改为0,表示关闭。 对于通过Unix域套接字进行的连接,此参数将被忽略。
keepalives_idle #控制在多少秒的不活动后,TCP应向服务器发送保持活动消息。值为零使用系统默认值。 对通过Unix域套接字进行的连接或禁用保持活动的连接,此参数将被忽略。 仅在支持TCP_KEEPIDLE或等效套接字选项的系统以及Windows上支持; 在其他系统上,它没有任何效果。
keepalives_interval #控制在服务器未确认的情况下重新传输TCP保持活动消息的秒数。值为零时使用系统默认值。 此参数在通过Unix域套接字进行连接或禁用保持活动时将被忽略。 仅在支持TCP_KEEPINTVL或等效套接字选项的系统和Windows上支持; 在其他系统上,此参数无效。
keepalives_count #控制在客户端与服务器之间连接被视为断开之前可以丢失的TCP keepalive数量。 值为零时使用系统默认值。对通过Unix域套接字建立的连接或禁用keepalives的连接,此参数将被忽略。 仅在支持TCP_KEEPCNT或等效套接字选项的系统上受支持; 在其他系统上,此参数无效。
tcp_user_timeout #控制在连接在强制关闭之前,传输数据可以保持未被确认的毫秒数。 值为零时使用系统默认值。此参数对通过Unix域套接字进行的连接无效。 仅在支持TCP_USER_TIMEOUT的系统上受支持;在其他系统上,它没有效果。
replication #这个选项确定连接是否应该使用复制协议而不是正常协议。这就是PostgreSQL复制连接以及诸如 pg_basebackup这样的工具在内部使用的方式,但也可以被第三方应用程序使用。 要了解复制协议的描述,请参考Section 53.4。
支持以下值(不区分大小写):
在物理或逻辑复制模式下,只能使用简单查询协议。
gssencmode #这个选项确定是否以及如何优先与服务器协商安全的GSS TCP/IP连接。有三种模式:
gssencmode在Unix域套接字通信中被忽略。如果PostgreSQL没有编译GSSAPI支持, 使用require选项将导致错误,而prefer将被接受,但libpq实际上不会尝试 进行GSSAPI加密连接。
sslmode #这个选项确定是否以及以何种优先级与服务器协商安全的SSL TCP/IP连接。有六种模式:
详细了解这些选项如何工作,请参阅Section 32.19。
sslmode被忽略用于Unix域套接字通信。 如果PostgreSQL没有SSL支持编译, 使用选项require、verify-ca或 verify-full会导致错误,而选项allow和prefer 将被接受,但libpq实际上不会尝试建立SSL 连接。
请注意,如果可能使用GSSAPI加密, 则优先使用该加密,而不考虑SSL的值。要在具有可用GSSAPI 基础设施(如Kerberos服务器)的环境中强制使用 SSL加密,还需将 gssencmode设置为disable。
requiressl #此选项已被sslmode设置所取代。
如果设置为1,则需要与服务器建立SSL连接(这相当于sslmode require)。libpq将拒绝连接,如果服务器不接受 SSL连接。如果设置为0(默认值), libpq将与服务器协商连接类型(相当于sslmode prefer)。此选项仅在PostgreSQL编译时启用SSL支持。
sslnegotiation #如果使用 SSL,此选项控制如何与服务器协商 SSL 加密。在默认的postgres模式下,客户端会先询问服务器是否支持 SSL;在direct模式下,客户端会在建立 TCP/IP 连接后直接开始标准 SSL 握手。传统的PostgreSQL协议协商能兼容更多不同的服务器配置;如果已知服务器支持直接SSL连接,则后一种方式可以减少一次往返,从而降低连接延迟,也允许使用与协议无关的 SSL 网络工具。直接 SSL 选项是在PostgreSQL 17 中引入的。
postgres执行PostgreSQL协议协商。如果未提供该选项,这是默认值。
direct在建立 TCP/IP 连接后直接开始 SSL 握手。仅当sslmode=require或更高时才允许使用该模式,因为更弱的设置可能在服务器不支持直接 SSL 握手时导致意外回退到明文认证。
sslcompression #如果设置为1,通过SSL连接发送的数据将被压缩。如果设置为0,将禁用压缩。默认值为0。 如果进行非SSL连接,则忽略此参数。
SSL压缩现在被认为是不安全的,不再建议使用。 OpenSSL 1.1.0默认禁用压缩, 许多操作系统发行版也在之前的版本中禁用了压缩,因此如果服务器不接受压缩,将此参数设置为on将不会产生任何效果。 PostgreSQL 14在后端完全禁用了压缩。
如果安全性不是主要考虑因素,压缩可以提高吞吐量,如果网络是瓶颈的话。如果CPU性能是限制因素,禁用压缩可以提高响应时间和吞吐量。
sslcert #这个参数指定客户端SSL证书的文件名,替换默认的 ~/.postgresql/postgresql.crt。 如果没有建立SSL连接,则此参数将被忽略。
sslkey #这个参数指定了用于客户端证书的密钥的位置。它可以指定一个文件名,该文件名将被用来替代默认的 ~/.postgresql/postgresql.key,或者它可以指定一个从外部“引擎” (引擎是OpenSSL可加载模块)获取的密钥。外部引擎规范应该包括一个由冒号分隔的引擎名称和 一个引擎特定的密钥标识符。如果没有进行SSL连接,则此参数将被忽略。
sslkeylogfile #这个参数指定libpq记录此 SSL 上下文所用密钥的位置。这对于调试PostgreSQL协议交互,或者借助Wireshark之类的网络检查工具分析客户端连接很有用。如果未建立 SSL 连接,或者使用的是LibreSSL(其不支持密钥记录),则会忽略此参数。密钥将按NSS格式记录。
密钥记录会在 keylog 文件中暴露潜在敏感信息。应当像处理sslkey文件一样谨慎处理 keylog 文件。
sslpassword #这个参数指定了在sslkey中指定的密钥的密码,允许客户端证书私钥在磁盘上以加密形式存储,即使交互式密码输入不可行。
指定此参数为任何非空值将抑制Enter PEM pass phrase: 当提供加密的客户端证书密钥给libpq时, OpenSSL默认会发出的提示。
如果密钥未加密,则忽略此参数。该参数对由OpenSSL引擎指定的密钥没有影响,除非引擎使用OpenSSL密码回调机制进行提示。
没有与此选项等效的环境变量,也没有在.pgpass中查找它的功能。它可以在服务文件连接定义中使用。 使用更复杂功能的用户应考虑使用OpenSSL引擎和类似PKCS#11或USB加密卸载设备的工具。
sslcertmode #此选项决定是否可以向服务器发送客户端证书,以及服务器是否必须请求客户端证书。共有三种模式:
disable即使客户端有可用证书(默认位置或通过sslcert提供),也绝不发送客户端证书。
allow(默认)如果服务器请求证书且客户端有证书可发,则可以发送证书。
require服务器必须请求证书。如果客户端没有发送证书而服务器仍成功认证了客户端,则连接将失败。
sslcertmode=require不会增加额外的安全性,因为无法保证服务器一定正确验证了证书;PostgreSQL服务器通常无论是否验证,都会向客户端请求 TLS 证书。该选项在排查更复杂的 TLS 配置时可能有用。
sslrootcert #这个参数指定一个包含SSL证书颁发机构(CA)证书的文件名。 如果文件存在,服务器的证书将被验证是否由这些机构之一签名。 默认值是~/.postgresql/root.crt。
sslcrl #这个参数指定SSL服务器证书吊销列表(CRL)的文件名。如果存在该文件中列出的证书,在尝试验证服务器证书时将被拒绝。 如果既没有设置sslcrl也没有设置sslcrldir, 则将采用~/.postgresql/root.crl。
sslcrldir #这个参数指定SSL服务器证书吊销列表(CRL)的目录名称。如果存在该目录中的文件中列出的证书,在尝试验证服务器证书时将被拒绝。
目录需要使用OpenSSL命令 openssl rehash或c_rehash进行准备。详细信息请参阅其文档。
sslcrl和sslcrldir可以一起指定。
sslsni #如果设置为1(默认值),libpq会在启用SSL的连接上设置TLS扩展“Server Name Indication”(SNI)。 通过将此参数设置为0,可以关闭此功能。
服务器名称指示可以被SSL感知代理使用,以便在不解密SSL流的情况下路由连接。 (请注意,这需要一个了解PostgreSQL协议握手的代理,而不仅仅是任何SSL代理。) 然而,SNI会使目标主机名以明文形式出现在网络流量中,因此在某些情况下可能不希望使用。
requirepeer #这个参数指定了服务器的操作系统用户名,例如requirepeer=postgres。 在建立Unix域套接字连接时,如果设置了这个参数,客户端会在连接开始时检查服务器进程是否在指定的用户下运行; 如果不是,则连接会因错误而中止。 这个参数可用于提供类似于在TCP/IP连接上使用SSL证书的服务器认证。 (请注意,如果Unix域套接字位于/tmp或其他公共可写位置, 任何用户都可以在那里启动一个服务器监听。使用这个参数来确保您连接到由受信任用户运行的服务器。) 此选项仅在实现了peer认证方法的平台上受支持;请参见Section 20.9。
ssl_min_protocol_version #这个参数指定连接允许的最低SSL/TLS协议版本。有效值为TLSv1, TLSv1.1,TLSv1.2和 TLSv1.3。支持的协议取决于所使用的 OpenSSL版本,旧版本不支持最现代的协议版本。 如果未指定,默认值为TLSv1.2,符合本文撰写时的行业最佳实践。
ssl_max_protocol_version #这个参数指定连接允许的最大SSL/TLS协议版本。有效值为TLSv1, TLSv1.1,TLSv1.2和 TLSv1.3。支持的协议取决于使用的OpenSSL 版本,旧版本不支持最新的协议版本。如果未设置,将忽略此参数,并且连接将使用后端定义的最大限制, 如果设置。设置最大协议版本主要用于测试或者某些组件无法使用较新协议时。
min_protocol_version #这个参数指定该连接允许的最低协议版本。默认情况下,允许使用 libpq所支持的任何 PostgreSQL协议版本, 目前即3.0。如果服务器至少不支持这一协议版本, 则连接将被关闭。
当前支持的值是3.0、3.2 和latest。latest等价于 正在使用的libpq版本所支持的最新协议版本, 目前即3.2。
max_protocol_version #这个参数指定要向服务器请求的协议版本。默认会使用 PostgreSQL协议的3.0版本; 但如果连接字符串指定了依赖更高协议版本的特性,则会使用 libpq支持的最新版本。如果服务器不支持客户端请求的协议版本, 连接会自动降级为服务器支持的较低次版本协议。连接尝试完成后, 你可以使用PQfullProtocolVersion()来确定 最终协商得到的确切协议版本。
当前支持的值是3.0、3.2 和latest。latest等价于 正在使用的libpq版本所支持的最新协议版本, 目前即3.2。
krbsrvname #用于使用GSSAPI进行认证时要使用的Kerberos服务名称。 这必须与服务器配置中指定的Kerberos认证服务名称匹配,才能成功进行认证。 (另请参见Section 20.6。) 默认值通常为postgres, 但在构建PostgreSQL时可以通过 --with-krb-srvnam选项进行更改 configure。 在大多数环境中,通常不需要更改此参数。 一些Kerberos实现可能需要不同的服务名称, 例如Microsoft Active Directory需要服务名称为大写(POSTGRES)。
gsslib #用于GSSAPI认证的GSS库。 目前,除了包含GSSAPI和SSPI支持的Windows构建之外,这将被忽略。 在这种情况下,将其设置为gssapi,以使libpq使用GSSAPI库进行认证,而不是默认的SSPI。
gssdelegation #将 GSS 凭证转发(委派)给服务器。默认值为0,表示不向服务器转发凭证。将其设置为1时,会在可能的情况下转发凭证。
scram_client_key #以 Base64 编码的 SCRAM client key。外部数据包装器或类似中间件可以利用它启用透传式 SCRAM 认证。一个实现示例见Section F.36.1.10。普通用户或客户端应用不应直接指定它。
scram_server_key #以 Base64 编码的 SCRAM server key。外部数据包装器或类似中间件可以利用它启用透传式 SCRAM 认证。一个实现示例见Section F.36.1.10。普通用户或客户端应用不应直接指定它。
service #用于额外参数的服务名称。它指定了pg_service.conf中保存额外连接参数的服务名称。 这允许应用程序只指定一个服务名称,以便可以集中维护连接参数。参见Section 32.17。
target_session_attrs #这个选项确定会话是否必须具有某些属性才能被接受。通常与多个主机名结合使用, 以便在多个主机中选择第一个可接受的候选项。有六种模式:
load_balance_hosts #控制客户端尝试连接可用主机和地址的顺序。一旦某次连接尝试成功,就不会再尝试其他主机和地址。该参数通常与多个主机名或返回多个 IP 地址的 DNS 记录一起使用。它还可以与target_session_attrs组合使用,例如只在备库之间进行负载均衡。连接一旦成功建立,随后在返回的连接上发出的所有查询都会发送到同一台服务器。目前有两种模式:
disable(默认)不在主机之间执行负载均衡。主机会按提供的顺序进行尝试,地址会按从 DNS 或 hosts 文件获得的顺序进行尝试。
random按随机顺序尝试主机和地址。这个值主要适用于同时打开多个连接的场景,甚至这些连接来自不同机器。这样就可以把连接负载分散到多个PostgreSQL服务器上。
虽然随机负载均衡由于其随机性几乎不会得到完全均匀的分布,但统计上会相当接近。这里有一个重要点:该算法使用两级随机选择。首先,主机会按随机顺序解析。其次,在解析下一个主机之前,会按随机顺序尝试当前主机解析得到的全部地址。在某些情况下,这种行为会显著偏斜各节点获得的连接数量,例如某些主机解析出的地址比其他主机更多时。但这种偏斜也可以被有意利用,例如通过在主机字符串中多次提供某台更大服务器的主机名,来增加它获得的连接数量。
使用这个值时,建议同时为connect_timeout配置一个合理的值。这样,如果某个参与负载均衡的节点没有响应,就会继续尝试新的节点。
oauth_issuer #如果服务器为该连接请求 OAuth 令牌,要联系的受信任签发者的 HTTPS URL。所有 OAuth 连接都必须设置此参数;它应当与服务器 HBA 配置中的issuer设置完全一致。
作为标准认证握手的一部分,libpq会向服务器请求一个发现文档,也就是一个提供一组 OAuth 配置参数的 URL。服务器必须提供一个可由oauth_issuer的各组成部分直接构造出来的 URL,并且该值必须与发现文档自身声明的签发者标识符完全一致,否则连接会失败。这是为了防止 OAuth 客户端遭受一类 “混淆攻击(mix-up attacks)”。
你也可以显式把oauth_issuer设置为 OAuth 发现所使用的/.well-known/ URI。在这种情况下,如果服务器要求使用不同的 URL,连接就会失败;不过,自定义 OAuth 流程也许能够通过使用先前缓存的令牌来加速标准握手。(此时也建议设置oauth_scope,因为客户端将没有机会向服务器询问正确的 scope 设置,而令牌的默认 scope 可能不足以完成连接。)libpq当前支持以下 well-known 端点:
/.well-known/openid-configuration
/.well-known/oauth-authorization-server
在 OAuth 连接握手期间,签发者拥有极高的权限。经验法则是:如果你不会信任某个 URL 的运营者来处理你对服务器的访问,或者不会信任其直接冒充你,那么这个 URL 就不应被信任为oauth_issuer。
oauth_client_id #由授权服务器发放的 OAuth 2.0 客户端标识符。如果PostgreSQL服务器为该连接请求 OAuth 令牌,并且没有安装自定义 OAuth 钩子来提供该令牌,那么就必须设置此参数;否则连接会失败。
oauth_client_secret #与 OAuth 授权服务器通信时要使用的客户端密码(如果有)。该参数是否必需由 OAuth 提供者决定;“public” 客户端通常不使用 secret,而 “confidential” 客户端通常会使用。
oauth_scope #发送给授权服务器的访问请求 scope,以 OAuth scope 标识符的空格分隔列表指定(该列表可以为空)。该参数是可选的,面向高级用法。
通常客户端会从PostgreSQL服务器获得合适的 scope 设置。如果使用这个参数,服务器请求的 scope 列表会被忽略。这可以防止不那么受信任的服务器向最终用户请求不恰当的访问 scope。不过,如果客户端的 scope 设置不包含服务器所要求的 scope,服务器很可能会拒绝已经签发的令牌,连接也会失败。
空 scope 列表的含义取决于提供者。OAuth 授权服务器可以选择签发带有“默认 scope”的令牌,不管那具体是什么;也可以完全拒绝该令牌请求。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。