Pgpool II
管理一个 PostgreSQL
服务器池,以实现单个 PostgreSQL
安装无法实现的一些功能。这些功能包括:
Pgpool-II
通过使用多个PostgreSQL
服务器提供高可用性 (HA
) 功能,以便它自动从服务器池中删除损坏的服务器以继续执行数据库任务。这称为自动故障转移(automatic failover)
。Pgpool-II
还为Pgpool-II
本身提供了一个HA
功能,称为Watchdog
。此外,Pgpool-II
采用复杂的仲裁算法来避免误报错误和脑裂问题,使整个HA
系统高度可靠。
Pgpool-II
将读取查询分布在多个PostgreSQL
服务器上以获得更高的性能。此功能称为负载平衡。 写查询被发送到主服务器(在流复制模式下)或所有服务器(在原生复制模式和快照隔离模式下)。在任何情况下,Pgpool-II
都会自动区分读查询和写查询。
除了这些基本功能之外,Pgpool-II
还提供了一些有用的功能,例如:
Pgpool-II
维护与PostgreSQL
服务器的已建立连接,并在具有相同属性(即用户名、数据库、协议版本和其他连接参数,如果有的话)的新连接进入时重用它们。它减少了连接开销,并改进了 系统的整体吞吐量。
Pgpool-II
可以通过执行一条命令进行数据库节点的在线恢复。 当在线恢复与自动故障转移一起使用时,通过故障转移分离的节点可以自动附加为备用节点。 也可以同步和附加新的PostgreSQL
服务器。
PostgreSQL
的最大并发连接数是有限制的,当达到这个数量时,新的连接会被拒绝。 但是,提高此最大连接数会增加资源消耗并对整体系统性能产生负面影响。Pgpool-II
对最大连接数也有限制,但是额外的连接会排队而不是立即返回错误。 但是,您可以配置为在超出连接限制时返回错误(4.1 或更高版本)。
Watchdog
可以协调多个Pgpool-II
,创建一个健壮的集群系统,避免单点故障或脑裂。 为避免脑裂,您至少需要3
个Pgpool-II
节点。Watchdog
可以针对其他pgpool-II
节点执行生命检查,以检测Pgpool-II
的故障。如果活动Pgpool-II
宕机,备用Pgpool-II
可以升级为活动,并接管Virtual IP
。
- 在内存中查询缓存允许保存一对
SELECT
语句及其结果。如果有相同的SELECT
进入,Pgpool-II
从缓存中返回值。由于不涉及SQL
解析和对PostgreSQL
的访问,因此使用内存缓存非常快。 另一方面,在某些情况下它可能比正常路径慢,因为它增加了存储缓存数据的一些开销。
Pgpool-II
使用 PostgreSQL
的后端和前端协议,并在后端和前端之间中继消息。 因此,数据库应用程序(前端)认为 Pgpool-II
是实际的 PostgreSQL
服务器,而服务器(后端)将 Pgpool-II
视为其客户端之一。因为 Pgpool-II
对服务器和客户端都是透明的,所以现有的数据库应用程序可以与 Pgpool-II
一起使用,几乎不需要更改其源代码。
Pgpool-II
适用于 Linux
、FreeBSD
和大多数类 UNIX
架构。不支持 Windows
。支持的 PostgreSQL
服务器版本为 7.4
或更高版本(某些功能可能不适用于旧版本的 PostgreSQL
)。您还必须确保所有 PostgreSQL
服务器都使用相同的主要版本。除此之外,我们不建议将不同的 PostgreSQL
安装与不同的构建选项混合使用:包括是否支持 SSL
、是否使用 --disable-integer-datetimes
、不同的块大小。这些可能会影响 Pgpool-II
的部分功能。PostgreSQL
次要版本的差异通常不是问题。但是,我们不会测试所有出现的次要版本,我们建议使用完全相同的 PostgreSQL
次要版本。
Pgpool-II
的生命始于 Tatsuo Ishii
的个人项目。在项目中它只是一个简单的连接池软件。所以 Pgpool
这个名字来源于这个事实。第一个版本于 2003
年公开。
2004
年,Pgpool 1.0
发布,带有原生复制功能(基于 SQL
语句的复制)。同年 2.0
发布了负载均衡,并支持第 3
版前端/后端协议。2005
年,添加了自动故障转移和主从模式支持。
2006
年,Pgpool
更名为 Pgpool-II
。第一个版本 1.0
取消了 Pgpool
中的许多限制,例如 Pgpool
中 PostgreSQL
服务器的数量最多为 2
个。 还添加了许多新功能,例如并行查询模式和 PCP
命令(PCP
代表 "Pgpool Control Protocol"
)。Pgpool
和 Pgpool-II
之间最重要的变化可能是项目从个人项目更改为 Pgpool Development Group
拥有的团体项目。
在命令概要中使用以下约定:括号([
和 ]
)表示可选部分。(在 Tcl
命令的概要中,使用问号 (?
) 代替,这在 Tcl
中很常见。)大括号({
和 }
)和竖线(|
)表示您必须选择一种替代方法。点 (...
) 表示前面的元素可以重复。
在提高清晰度的地方,SQL
命令前面有提示符 =>
,shell
命令前面有提示符 $
。 但是,通常不会显示提示。
administrator
通常是负责安装和运行服务器的人。用户可以是正在使用或想要使用 Pgpool-II
系统的任何部分的任何人。这些术语不应被解释得太狭隘;本文档没有关于系统管理程序的固定假设。
Pgpool-II
网站是提供有关Pgpool-II
官方信息的中心位置:下载、文档、常见问题解答、邮件列表存档等。
- 邮件列表是回答您的问题、与其他用户分享经验以及联系开发人员的好地方。有关详细信息,请参阅
Pgpool-II
网站。
pgpool-II
是一个开源项目。因此,它依赖于用户社区的持续支持。当您开始使用Pgpool-II
时,您将依赖其他人的帮助,无论是通过文档还是通过邮件列表。考虑回馈您的知识。阅读邮件列表并回答问题。 如果您学到了文档中没有的内容,请将其写下来并贡献出来。如果您向代码添加功能,请贡献它们。
本节介绍 Pgpool-II
的当前限制。
PostgreSQL
的功能
- 如果您使用
pg_terminate_backend()
停止后端,这将触发故障转移。发生这种情况的原因是PostgreSQL
为终止的后端发送与完全关闭postmaster
完全相同的消息。3.6
版之前没有解决方法。从版本3.6
开始,此限制已得到缓解。如果函数的参数(即进程 ID
)是常量,则可以安全地使用该函数。 在扩展协议模式下,您无法使用该功能。
多语句查询(单行多个 SQL
命令)总是发送到主节点(在流复制模式下)或主节点(在其他模式下)。通常 Pgpool-II
将查询分派到适当的节点,但不适用于多语句查询。
-
在
replication
模式或native replication
模式下,支持trust
和pam
方法。自Pgpool-II 3.0
起也支持md5
。 使用身份验证文件pool_passwd
支持md5
。自Pgpool-II 4.0
起,还支持scram-sha-256
、证书和明文密码。pool_passwd
是认证文件的默认名称。以下是启用md5
身份验证的步骤:- 以数据库的操作系统用户身份登录并输入:
pg_md5 --md5auth --username=your_username your_passwd
用户名和
md5
加密密码注册到pool_passwd
中。 如果pool_passwd
还不存在,pg_md5
命令会自动为你创建它。pool_passwd
的格式是username:encrypted_passwd
。- 您还需要将适当的
md5
条目添加到pool_hba.conf
。 - 请注意,用户名和密码必须与在
PostgreSQL
中注册的相同。 - 更改
md5
密码后(当然在pool_passwd
和PostgreSQL
中),您需要执行pgpool reload
。
- 在流复制模式下,
Pgpool-II
支持大对象。 - 在原生复制模式下,如果后端是
PostgreSQL 8.1
或更高版本,Pgpool-II
支持大对象。为此,您需要在pgpool.conf
中启用lobj_lock_table
指令。但是,不支持使用后端函数lo_import
进行大对象复制。 - 在其他模式下,包括 Slony 模式,不支持大对象。
- 创建/插入/更新/删除临时表始终在原生复制模式下的主节点上执行。 这些表上的
SELECT
也在primary
表上执行。但是,如果临时表名在SELECT
中用作文字,则无法检测到它,并且SELECT
将进行负载均衡。 这将触发"not found the table"
错误或将找到另一个具有相同名称的表。 为避免此问题,请使用SQL
注释。 - 请注意,用于访问系统目录的查询中使用的此类文字表名称确实会导致上述问题。
psql
的\d
命令产生这样的查询:
SELECT 't1'::regclass::oid;
在这种情况下,Pgpool-II
总是将查询发送到主节点并且不会导致问题。
如果您使用的是 PostgreSQL 8.3
或更高版本,则通过在 reset_query_list
中指定 DISCARD ALL
将在会话结束时删除由 CREATE TEMP TABLE
创建的表。
对于 8.2.x
或更早版本,由 CREATE TEMP TABLE
创建的表在退出会话后不会被删除。这是因为连接池,从 PostgreSQL
的后端角度来看,它使会话保持活动状态。为避免这种情况,您必须通过发出 DROP TABLE
显式删除临时表,或在事务块内使用 CREATE TEMP TABLE ... ON COMMIT DROP
。
无法保证使用上下文相关机制(例如 random number
, transaction ID
, OID
, SERIAL
, sequence
)提供的任何数据将在多个后端正确复制。 对于 SERIAL
,启用 insert_lock
将有助于复制数据。insert_lock
还有助于 SELECT setval()
和 SELECT nextval()
。
使用 CURRENT_TIMESTAMP
、CURRENT_DATE
、now()
的 INSERT/UPDATE
将被正确复制。使用 CURRENT_TIMESTAMP
、CURRENT_DATE
、now()
作为默认值的表的 INSERT/UPDATE
也将被正确复制。 这是通过在查询执行时用从 primary
获取的常量替换这些函数来完成的。 但是有一些限制:
在 Pgpool-II 3.0
或之前的版本中,在某些情况下,表默认值中时态数据的计算并不准确。 例如下面的表定义:
CREATE TABLE rel1(
d1 date DEFAULT CURRENT_DATE + 1
)
被视为:
CREATE TABLE rel1(
d1 date DEFAULT CURRENT_DATE
)
Pgpool-II 3.1
或更高版本可以正确处理这些情况。 因此,"d1"
列将明天作为默认值。但是,如果使用扩展协议(例如,在 JDBC
、PHP PDO
中使用)或 PREPARE
,则此增强不适用。
请注意,如果列类型不是时间类型,则不执行重写。这样的例子:
foo bigint default (date_part('epoch'::text,('now'::text)::timestamp(3) with time zone) * (1000)::double precision)
假设我们有下表:
CREATE TABLE rel1(
c1 int,
c2 timestamp default now()
)
我们可以复制
INSERT INTO rel1(c1) VALUES(1)
因为这变成
INSERT INTO rel1(c1, c2) VALUES(1, '2009-01-01 23:59:59.123456+09')
然而,
INSERT INTO rel1(c1) SELECT 1
无法转换,因此无法在当前实现中正确复制。 仍然会插入值,根本没有任何转换。
SQL 类型命令SQL
类型的命令不能用于扩展查询模式。
Pgpool-II
不会在客户端和PostgreSQL
之间对多字节字符进行编码转换。客户端和后端的编码必须相同。
Pgpool-II
不能处理多语句查询。但是,当Pgpool-II
通过psql
连接时,是没有问题的。psql
解析多条语句,逐个发送一条语句。
libpq
在构建Pgpool-II
时被链接。libpq
版本必须是3.0
或更高版本。使用libpq 2.0
版构建Pgpool-II
将失败。
- 当客户端连接到
PostgreSQL
时,PostgreSQL
将一些parameter/value
对发送回客户端。该协议称为ParameterStatus
。参数/值对可以通过libpq
的PQParameterStatus
等API
提取。Pgpool-II
从多个PostgreSQL
服务器收集ParameterStatus
值,并且这些值可能在服务器之间有所不同。一个典型的例子是in_hot_standby
,它是在PostgreSQL 14
中引入的。该变量的值在主服务器为off
和备用服务器上为on
。问题是,Pgpool-II
必须只返回其中一个客户端。 在这种情况下,它选择主服务器报告的值。所以PQParameterStatus
将返回off
。 另一方面,当客户端发出show in_hot_standby
时,返回值可以on
或off
,具体取决于会话的负载均衡节点。 - 请注意,如果服务器之间的值不同,
Pgpool-II
将发出除in_hot_standby
之外的日志消息。这是为了防止日志文件被淹没,因为in_hot_standby
总是不同的。
PostgreSQL
具有set_config
功能,它允许在当前会话中更改参数值,如SET
命令(实际上set_config
比SET
具有更多功能。有关详细信息,请参阅PostgreSQL
手册)。当Pgpool-II
在集群模式设置为streaming_replication
的情况下运行时,它只将函数发送到主服务器。由于该函数不发送到备用服务器,因此每个服务器的参数值不同。为避免该问题,您可以使用SET
命令代替set_config
。 由于SET
命令已发送到用于此会话的所有服务器,因此不会发生此问题。但是,如果您使用超过2
个PostgreSQL
服务器,则需要禁用statement_level_load_balance
并使用SET
命令。这是因为,如果启用了statement_level_load_balance
,查询可能会发送到除主服务器和分配给负载均衡节点的服务器之外的第三台服务器。- 如果需要使用
set_config
,请关闭session
的负载均衡(不仅对于set_config
,还应在整个会话中禁用负载均衡)。你可以通过牺牲性能来避免这个问题。
- 「在 Kubernetes 上运行 Pgpool-Il」实现 PostgreSQL 查询(读)负载均衡和连接池