PostgreSQL 14中连接参数target_session_attrs增强
本文讨论PostgreSQL 14数据库连接参数target_session_attrs增强的功能,并解释该功能背后的历史、如何使用它以及它提供的各种好处。
背景
很多PG客户端程序使用C客户端libpq库访问数据库。libpq提供了一系列函数,允许连接PG后台服务并将查询传送过去,同时还可以接收查询返回的结果。
通过libpq,PG支持一个连接字符串,指定多个host+port。依次尝试每个host+port直到成功建立连接。
PG10中引入指定多个hosts的功能。同时增加了参数target_session_attrs,允许指定连接的后台server类型。
支持下面的参数值:
从PG11开始,Fujitsu提供了额外的参数值,不仅要满足其他连接类型,还要提高内部效率,以验证参数并建立连接。因此与PG社区开始了漫长的审查、咨询、改进的过程。涉及:
多名开发人员;许多补丁版本和补丁集更改;社区许多成员的反馈,有时会有不同意见和想法;一些成员对附加功能的请求;提交者本人的最终改进、调整与简化。
最终libpq增强功能在PG14提交了。
功能概述
PG14中target_session_attrs值如下,高亮显示的是新值:
注意,由于default_transaction_read_only设置成on,PG的server可以是只读但不能是hot standby模式。
支持的客户端
任何使用libpq库的客户端都能够使用target_session_attrs以及此处描述的改进的功能。支持psycopg2(python驱动)、psqlODBC(c 语言接口的驱动)。但是不包括JDBC驱动和NpgSql。JDBC支持targetServerType提供类似的功能,允许的值有primary/secondary/preferSecondary。NpgSql目前没有类似功能。
连接性能的提升
target_session_attrs增加了新值,当连接到PG14或之后的版本时,性能会有所提升。通过使用与会话状态相关的配置变量来实现:
服务器在成功连接时直接向客户端报告这些信息,节省了额外的网络往返时间以确定会话状态。因此连接到旧版本服务时,会发出SHOW和SELECT查询以检测会话只读或热备状态。注意,若服务在会话期间被提升成主,则in_hot_standby也会报告给客户端。
案例
Psql使用libpq,可以无需任何编码测试target_session_attrs。下面显示了尝试连接2个可能的本地服务其中一个服务时,使用不同target_session_attrs值的简单例子。
1、创建本地服务实例testdb1和testdb2(分别运行在端库5432和5433)
$ pg_ctl -D ./testdb1 initdb
$ pg_ctl -D ./testdb2 initdb
$ pg_ctl -D ./testdb1 -o '-p 5432' -l testdb_1.log start
$ pg_ctl -D ./testdb2 -o '-p 5433' -l testdb_2.log start
2、尝试连接仅接受只读事务的服务
$ psql "host=localhost,localhost port=5432,5433 dbname=postgres target_session_attrs=read-only"
psql: error: connection to server at "localhost" (::1), port 5432 failed: session is not read-only
connection to server at "localhost" (::1), port 5433 failed: session is not read-only
连接失败,因为2个实例仅接受读写事务。
3、改变testdb2使其仅接受只读事务,更改testdb2/postgresql.conf添加default_transaction_read_only=on并重启。
$ pg_ctl -D ./testdb2 -o '-p 5433' -l testdb_2.log restart
4、尝试连接到只读server
$ psql "host=localhost,localhost port=5432,5433 dbname=postgres target_session_attrs=read-only"
psql (14devel)
Type "help" for help.
postgres=# show
port;
port
------
5433
(1 row)
5、尝试连接hot standby的server
$ psql "host=localhost,localhost port=5432,5433 dbname=postgres target_session_attrs=standby"
psql: error: connection to server at "localhost" (::1), port 5432 failed: server is not in hot standby mode
connection to server at "localhost" (::1), port 5433 failed: server is not in hot standby mode
连接失败,因为没有hot standby模式的实例
6、尝试连接primary server
$ psql "host=localhost,localhost port=5432,5433 dbname=postgres target_session_attrs=primary"
psql (14devel)
Type "help" for help.
postgres=# show
port;
port
------
5432
(1 row)
7、连接到一个server,最好是处于热备模式的
$ psql "host=localhost,localhost port=5432,5433 dbname=postgres target_session_attrs=prefer-standby"
psql (14devel)
Type "help" for help.
postgres=# show
port;
port
------
5432
(1 row)
总结
支持的target_session_attrs新值,允许客户端选择需要的目标服务连接时进行更精细的粒度,并协助多主机连接功能。还提供了一种基本的扩展形式,例如允许将只读请求重定向到备服务,以减少主服务的负载。最后新值可以允许多主机连接字符串更好地与某些故障切换解决方案一起公众,以重新连接到可用的服务。