听话的板栗 · pgpool-II 用户手册· 1 月前 · |
大气的针织衫 · pgpool-II user manual· 1 年前 · |
坚强的吐司 · pgpool-II 用户手册· 1 年前 · |
纯真的柑橘 · 輸入資料流成員函式 | Microsoft ...· 3 月前 · |
无邪的木瓜 · Material Design ...· 3 月前 · |
乐观的签字笔 · Error: Cannot resolve ...· 6 月前 · |
骑白马的小蝌蚪 · 界面开发工具Telerik UI for ...· 6 月前 · |
想旅行的熊猫 · asp.net core - ...· 9 月前 · |
如果数据库进行了复制(可能运行在复制模式或者主备模式下), 则在任何一台服务器中执行一个 SELECT 查询将返回相同的结果。 pgpool-II 利用了复制的功能以降低每台 PostgreSQL 服务器的负载。 它通过分发 SELECT 查询到所有可用的服务器中,增强了系统的整体吞吐量。 在理想的情况下,读性能应该和 PostgreSQL 服务器的数量成正比。 负载均很功能在有大量用户同时执行很多只读查询的场景中工作的效果最好。
PostgreSQL 会限制当前的最大连接数,当到达这个数量时,新的连接将被拒绝。 增加这个最大连接数会增加资源消耗并且对系统的全局性能有一定的负面影响。 pgpool-II 也支持限制最大连接数,但它的做法是将连接放入队列,而不是立即返回一个错误。
使用并行查询时,数据可以被分割到多台服务器上, 所以一个查询可以在多台服务器上同时执行,以减少总体执行时间。 并行查询在查询大规模数据的时候非常有效。
pgpool-II 使用 PostgreSQL 的前后台程序之间的协议,并且在前后台之间传递消息。 因此,一个(前端的)数据库应用程序认为 pgpool-II 就是实际的 PostgreSQL 数据库, 而后端的服务进程则认为 pgpool-II 是它的一个客户端。 因为 pgpool-II 对于服务器和客户端来说是透明的, 现有的数据库应用程序基本上可以不需要修改就可以使用 pgpool-II 了。
通过 pgpool-II 使用 SQL 有一些限制条件。参考 限制 获得详细信息。pgpool-II 可以运行在 Linux,Solaris,FreeBSD 以及基本上所有的类 UNIX 架构的平台上。 不支持 Windows。支持 6.4 以上版本的 PostgreSQL 服务器。 然而,如果要使用并行查询功能,需要 7.4 或更高版本。
如果你在使用 7.3 或者更老版本的 PostgreSQL,一些 pgpool-II 的功能将无法使用。 但无论如何你不应该还在用这么老的版本了。
你还要确保你所有的 PostgreSQL 服务器运行相同主版本号的 PostgreSQL 程序。另外,如果你想要使用在线恢复,硬件架构和操作系统必须一致。 另外,我们不推荐在使用不同编译参数编译的 PostgreSQL:包括是否支持 SSL,是否使用了 --disable-integer-datetimes 参数或者不同的块大小。 这些可能对 pgpool-II 的部分功能有影响。 通常情况下,小版本号不同没有什么影响。但是我们没有针对小版本的区别做全面测试,因此我们建议还是使用相同的版本的 PostgreSQL。
从源码安装 pgpool-II 需要 2.9 甚至或更高版本的 gcc,以及 GNU make。 而且,pgpool-II 需要链接到 libpq 库,所以在构建 pgpool-II 的机器上必须安装 libpq 库和它的开发头文件。 另外,还需要 OpenSSL 库和它的头文件以便在 pgpool-II 中提供 OpenSSL 支持。
在解压源码包后,执行以下配置脚本。
./configure如果你需要非默认的值,有以下选项可以设置:
--prefix=path
pgpool-II 的二进制程序和文档将被安装到这个目录。默认值为
/usr/local
--with-pgsql=path
PostgreSQL 的客户端库安装的顶层目录。默认值由
pg_config
提供
--with-openssl
pgpool-II 程序将提供 OpenSSL 支持。默认是禁用 OpenSSL 支持的。
V2.3 -
--enable-sequence-lock
在 pgpool-II 3.0 系列中使用 insert_lock 兼容。pgpool-II 针对序列表中的一行进行加锁。PostgreSQL 8.2 或2011年六月以后发布的版本无法使用这种加锁方法。
V3.1 -
--enable-table-lock
在 pgpool-II 2.2 和 2.3 系列中使用 insert_lock 兼容。pgpool-II 针对被插入的表进行加锁。这种锁因为和 VACUUM 冲突,已被废弃。
V3.1 -
--with-memcached=path
pgpool-II 的二进制程序将使用
memcached
作为
基于内存的查询缓存
。你必须先安装
libmemcached
。
V3.2 -
如果你在使用 PostgreSQL 8.0 或之后的版本,强烈推荐在需要访问的 PostgreSQL
中安装 pgpool_regclass 函数,因为它被 pgpool-II 内部使用。
如果不这样做,在不同的 schema 中处理相同的表名会出现问题(临时表不会出问题)。
cd pgpool-II-x.x.x/sql/pgpool-regclass
make install
psql -f pgpool-regclass.sql template1
应在在每台通过 pgpool-II 访问的数据库中执行 pgpool-regclass.sql。
你不需要在你执行“psql -f pgpool-regclass.sql template1”后建立的数据库中这么做,
因为这个模板数据库将被克隆成新建的数据库。
pgpool-II 的默认配置文件为
/usr/local/etc/pgpool.conf
和
/usr/local/etc/pcp.conf
。pgpool-II 中有很多操作模式。
每种模式都有相关的可被开启或者禁用的功能,而且有相关的配置项用于控制它们的行为。
pcp.conf
pgpool-II 有一个控制接口,管理员可以通过它远程收集 pgpool-II 的状态信息或者终止 pgpool-II 进程。
pcp.conf
是用于这个接口认证的用户/密码文件。
所有的模式都需要先设置
pcp.conf
文件。
一个
$prefix/etc/pcp.conf.sample
文件在 pgpool-II 安装时已经被创建。
重命名这个文件为
pcp.conf
并添加你要的用户名和密码到其中。
cp $prefix/etc/pcp.conf.sample $prefix/etc/pcp.conf
空行或者以“
#
”开始的行将被认为是注释,会被忽略掉。一个用户名和对应的密码必须以以下的方式写成一行。
[password encrypted in md5]
可以通过
$prefix/bin/pg_md5
命令生成。
pg_md5 -p
password: <your password>
./pg_md5 foo
acbd18db4cc2f85cedef654fccc4a4d8
pcp.conf
对于运行 pgpool-II 的用户必须可读。
pgpool.conf
就像之前说的,每种操作模式在
pgpool.conf
文件中有它对应的配置项。一个
$prefix/etc/pgpool.conf.sample
文件在 pgpool-II 安装时已经被创建。重命名这个文件为
pgpool.conf
并修改它的内容。
cp $prefix/etc/pgpool.conf.sample $prefix/etc/pgpool.conf
针对每种不同的模式,提供了附加的示例 pgpool.conf。
V2.3 -
指定 pgpool-II 将接受 TCP/IP 连接的主机名或者IP地址。
'*'
将接受所有的连接。
''
将禁用 TCP/IP 连接。默认为
'localhost'
。总是支持接受通过 UNIX 域套接字发起的连接。需要重启 pgpool-II 以使改动生效。
pgpool-II 监听 TCP/IP 连接的端口号。默认为 9999。需要重启 pgpool-II 以使改动生效。
pgpool-II 建立用于建立接受 UNIX 域套接字连接的目录。默认为
'/tmp'
。注意,这个套接字可能被 cron 任务删除。我们建议设置这个值为
'/var/run'
或类似目录。需要重启 pgpool-II 以使改动生效。
PCP 进程接受连接的端口号。默认为 9898。本参数必须在服务器启动前设置。
PCP 进程用于建立接受 UNIX 域套接字连接的目录。默认为
'/tmp'
。注意,这个套接字可能被 cron 任务删除。我们建议设置这个值为
'/var/run'
或类似目录。需要重启 pgpool-II 以使改动生效。
本参数定义了 PostgreSQL 服务器的 UNIX 域套接字目录。
默认为
'/tmp'
.
本参数必须在服务器启动前设置。
PCP 连接超时值,单位为秒。如果客户端在设置的秒数内没有响应,PCP 关闭到这个客户端的连接。默认为 10 秒。0 表示没有超时。如果你改变了这个值,需要重新加载 pgpool.conf 以使变动生效。
预先生成的 pgpool-II 服务进程数。默认为 32。num_init_children 也是 pgpool-II 支持的从客户端发起的最大并发连接数。如果超过 num_init_children 数的客户端尝试连接到 pgpool-II,它们将被阻塞(而不是拒绝连接),直到到任何一个 pgpool-II 进程的连接被关闭为止。最多有 2*num_init_children 可以被放入等待队列。
对于以上内容的一些提示:
归纳起来,max_pool,num_init_children,max_connections 和 superuser_reserved_connections 必须符合以下规则: max_pool*num_init_children <= (max_connections - superuser_reserved_connections) (不需要取消查询) max_pool*num_init_children*2 <= (max_connections - superuser_reserved_connections) (需要取消查询) 本参数必须在服务器启动前设置。
pgpool-II 子进程的生命周期,单位为秒。如果子进程空闲了这么多秒,它将被终止,一个新的子进程将被创建。这个参数是用于应对内存泄露和其他不可预料错误的一个措施。默认值为 300 (5分钟)。0 将禁用本功能。注意它不影响尚未接受任何连接的进程。如果改变了这个值,你需要重新加载 pgpool.conf 以使变动生效。
当 pgpool-II 子进程处理这么多个客户端连接后,它将被终止。这个参数在繁忙到 child_life_time 和 connection_life_time 永远不会触发的服务器上有效。如果你改变了这个值,需要重新加载 pgpool.conf 以使变动生效。
当一个客户端在执行最后一条查询后如果空闲到了 client_idle_limit 秒数,到这个客户端的连接将被断开。这在避免 pgpool 子进程被懒客户端占用或者探测断开的客户端和 pgpool 之间的 TCP/IP 连接非常有用。如果你改变了这个值,需要重新加载 pgpool.conf 以使变动生效。
指定 pgpool 认证超时的时长。0 指禁用超时,默认值为 60 。如果你改变了这个值,需要重新加载 pgpool.conf 以使变动生效。
pgpool-II 支持多种记录服务器消息的方式,包括 stderr 和 syslog。默认为记录到 stderr。
注:要使用syslog 作为 log_destination 的选项,你将需要更改你系统的 syslog 守护进程的配置。pgpool-II 可以记录到 syslog 设备 LOCAL0 到 LOCAL7 (参考 syslog_facility), 但是大部分平台的默认的 syslog 配置将忽略这些消息。你需要添加如下一些内容 local0.* /var/log/pgpool.log
到 syslog 守护进程的配置文件以使它生效。
如果本值被设置为 true ,则将在日志中添加时间戳。默认值为 true。如果你改变了这个值,需要重新加载 pgpool.conf 以使变动生效。
如果为 true,进入的连接将被打印到日志中。如果你改变了这个值,需要重新加载 pgpool.conf 以使变动生效。
如果为 true,ps 命令将显示客户端的主机名而不是 IP 地址。而且,如果 log_connections 被开启,也会将主机名写入日志。如果你改变了这个值,需要重新加载 pgpool.conf 以使变动生效。
当设置为 true 时生成 SQL 日志消息。这类似于 PostgreSQL 中的 log_statement 参数。即使调试选项没有在启动的时候传递到 pgpool-II,它也会产生日志。
类似于 log_statement,除了它是针对每个 DB 节点产生日志外。例如它对于确定复制是否正常运行非常有用。如果你改变了这个值,需要重新加载 pgpool.conf 以使变动生效。
当记录日志到 syslog 被启用,本参数确定被使用的 syslog “设备”。你可以使用 LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7;默认为 LOCAL0。还请参考你系统的 syslog 守护进程的文档。
当记录日志到 syslog 被启用,本参数确定用于标记 syslog 中 pgpool-II 消息的程序名。默认为“pgpool”。
调试消息详细程度级别。0 表示没有消息。大于 1 表示更详细的消息。默认值为 0。
在执行失效故障切换前尝试的最大失效健康检查次数。这个参数对于网络不稳定的时,健康检查失败但主节点依旧正常的情况下非常有效。默认值为 0,也就是不重试。如果你想启用 health_check_max_retries,建议你禁用 fail_over_on_backend_error 。 如果你改变了 health_check_max_retries,需要重新加载 pgpool.conf。
失效健康检查重试的间隔时间(单位为秒)( health_check_max_retries > 0 时有效 )。如果为 0 则立即重试(不延迟)。如果你改变了 health_check_retry_delay,需要重新加载 pgpool.conf。 当进行故障切换时,pgpool 杀掉它的所有子进程,这将顺序终止所有的到 pgpool 的会话。然后,pgpool 调用 failover_command 并等待它完成。然后,pgpool 启动新的子进程并再次开始从客户端接受连接。
指出连接到 PostgreSQL 后台程序的地址。它用于 pgpool-II 与服务器通信。如果你改变了这个值,需要重新加载 pgpool.conf 以使变动生效。
对于 TCP/IP 通信,本参数可以是一个主机名或者IP地址。如果它是从斜线开始的,它指出是通过 UNIX 域套接字通信,而不是 TCP/IP 协议;它的值为存储套接字文件所在的目录。如果 backend_host 为空,则它的默认行为是通过
/tmp
中的 UNIX 域套接字连接。
可以通过在本参数名的末尾添加一个数字来指定多个后台程序(例如
backend_hostname0
)。这个数字对应为“数据库节点 ID”,是从 0 开始的正整数。被设置数据库节点ID为 0 的后台程序后台程序将被叫做“主数据库”。当定义了多个后台程序时,即使主数据库当机后依然能继续(某些模式下不行)。在这种情况下,存活的最小的数据库节点编号的数据库将被变成新的主数据库。
请注意有编号为 0 的节点在流复制中没有其他意义。但是,你需要注意数据库节点是不是“主节点”。请参考 流复制 获得更多细节。
如果你只计划使用一台 PostgreSQL 服务器,可以通过
backend_hostname0
指定。
backend_port0
)。如果你只计划使用一台 PostgreSQL 服务器,可以通过
backend_port0
指定。
可以通过配置本参数后重新加载配置文件添加新的后台端口。但是,对已有的值无法更新,所以这种情况下你必须重启 pgpool-II。
指定后台程序的负载均衡权重。可以通过在本参数名的末尾添加一个数字来指定多个后台程序(例如
backend_weight0
)。如果你只计划使用一台 PostgreSQL 服务器,可以通过
backend_weight0
指定。
在原始模式中,请将本值设置为 1。
可以通过配置本参数后重新加载配置文件添加新的负载均衡权重。但是,对已有的值无法更新,所以这种情况下你必须重启 pgpool-II。 在 pgpool-II 2.2.6/2.3 或者更新的版本中,你可以通过重新加载配置文件来改变本值。但这只对新连接的客户会话生效。这在主备模式中可以避免任何执行一些管理工作的查询被发送到备用节点上。
指定后台的数据库实例的目录。可以通过在本参数名的末尾添加一个数字来指定多个后台程序(例如
backend_data_directory0
)。如果你不打算使用在线恢复,你可以不设置本参数。
控制大量的后台程序的行为。可以通过在本参数名的末尾添加一个数字来指定多个后台程序(例如
backend_flag0
)
当前支持以下的内容。多个标志可以通过“|”来分隔。
ALLOW_TO_FAILOVER
允许故障切换或者从后台程序断开。本值为默认值。指定本值后,不能同时指定 DISALLOW_TO_FAILOVER 。
DISALLOW_TO_FAILOVER
不允许故障切换或者从后台程序断开。本值在你使用 HA(高可用性)软件例如 Heartbeat 或者 Packmaker 来保护后台程序时非常有用。
本值为默认值。指定本值后,不能同时指定 DISALLOW_TO_FAILOVER 。
如果设置为 ture,则启用了到前端程序和后端程序的连接的 ssl 支持。注意为了能与前端程序进行 SSL 连接,必须设置
ssl_key
和
ssl_cert
。
SSL 默认被关闭。就像在 pgpool-II 的安装 小节所说的,注意必须在编译时配置 OpenSSL 支持才能打开 SSL 支持。
如果修改了 SSL 相关的设置, pgpool-II 守护进程必须重启。
对于进入的连接使用的私钥文件所在路径。
本选项没有默认值,如果本值不设置,则对于进入的连接将禁用 SSL。
本选项没有默认值,如果本值不设置,则对于进入的连接将禁用 SSL。 关系缓存的生命周期。0(默认值)表示没有缓冲区过期。 关系缓存用于缓存用来获取包含表结构信息或一个表是不是一个临时表等大量信息的相关的 PostgreSQL 系统 catalog 的查询结果。缓存位于 pgpool 子进程的本地,并被保存到它的生命结束。 如果某些人使用了 ALTER TABLE 修改了表结构或其他类似内容,关系缓存不再一致。 为了这个目的,relcache_expire 控制缓存的生命周期。
证书处理不在本文档讨论范围。postgresql.org 的 Secure TCP/IP Connections with SSL 页面指出了一些用来生成自签名证书的示例命令。
如果定义了多个服务器,可以在原始模式中进行故障切换。
pgpool-II 在普通操作中通常访问
backend_hostname0
指定的后台程序。
如果 backend_hostname0 因为某些原因不能正常工作,pgpool-II 尝试访问 backend_hostname1 指定的后台程序。
如果它也不能正常工作,pgpool-II 尝试访问 backend_hostname2,3 等等。
在连接池模式中,所有在原始模式中的功能以及连接池功能都可以使用。要启用本模式,设置原始模式的配置参数以及以下的参数。
在 pgpool-II 子进程中缓存的最大连接数。当有新的连接使用相同的用户名连接到相同的数据库,pgpool-II 将重用缓存的连接。如果不是,则 pgpool-II 建立一个新的连接到 PostgreSQL。如果缓存的连接数达到了 max_pool,则最老的连接将被抛弃,并使用这个槽位来保存新的连接。默认值为 4。请小心通过 pgpool-II 进程到后台的连接数可能达到
num_init_children
*
max_pool
个。需要重启 pgpool-II 以使改动生效。
缓存的连接的过期时长,单位为秒。过期的缓存连接将被关闭。默认值为 0,表示缓存的连接将不被关闭。
指定在推出一个会话时发送到后台程序的SQL命令。多个命令可以通过“;”隔开。默认为以下的设置但你可以根据你的需求改变。 reset_query_list = 'ABORT; DISCARD ALL' 不同版本的 PostgreSQL 需要使用不同的命令。以下为推荐的设置。 PostgreSQL 版本reset_query_list 的值 7.1 或更老的版本ABORT 7.2 到 8.2ABORT; RESET ALL; SET SESSION AUTHORIZATION DEFAULT 8.3 或更新的版本ABORT; DISCARD ALL
当设置为 true 时,当不同的后台程序返回不同的包类型时,则和其他后台程序差别最大的后台程序将被退化。 一个典型的用例为一个事务中的 SELECT 语句,在 replicate_select 设置为 true 的情况下,一个 SELECT 语句从不同的后台程序中返回不同的行数。非 SELECT 语句也可能触发这种情况。 例如,一个后台程序执行 UPDATE 成功但其他的失败。注意 pgpool 不会检查 SELECT 返回的记录的内容。如果设置为 false,则会话被终止但后台程序不被退化。默认值为 false。
当设置为 true 时,在执行 INSERT/UPDATE/DELETE 后不同的后台程序返回不同的生效记录数,则和其他后台程序差别最大的后台程序将被退化。如果设置为 false,则会话被终止但后台程序不被退化。默认值为 false。
指定一系列用逗号隔开的 不会 更新数据库的函数名。在复制模式中,不在本列表中指定的函数将即不会被负载均衡,也不会被复制。在主备模式中,这些 SELECT 语句只被发送到主节点。
你可以使用正则表达式来匹配函数名,例如你通过前缀“get_”或“select_”来作为你只读函数的开头: white_function_list = 'get_.*,select_.*'
指定一系列用逗号隔开的 会 更新数据库的函数名。在复制模式中,在本列表中指定的函数将即不会被负载均衡,也不会被复制。在主备模式中,这些 SELECT 语句只被发送到主节点。
你可以使用正则表达式来匹配函数名,例如你通过前缀“set_”、“update_”、“delete_”或“insert_”来作为你只读函数的开头:
black_function_list = 'nextval,setval,set_.*,update_.*,delete_.*,insert_.*' 以上两项不能同时配置。在 pgpool-II 3.0 之前,nextval() 和 setval() 是已知的会写入数据库的函数。你可以通使用 white_function_list 好 balck_function_list 来做到: white_function_list = '' black_function_list = 'nextval,setval,lastval,currval'
注意我们在 nextval 和 setval 后面追加了 lastval 和 currval。虽然 lastval() 和 currval() 不是会写入的函数,但添加 lastval() 和 currval() 可以避免这些函数被无意地被负载均衡到其他的数据库节点而导致错误。添加到 black_function_list 将避免它们被负载均衡。
当设置为 true,pgpool-II 在复制模式中将复制 SELECT 语句。如果为 false,则 pgpool-II 只发送它们到主数据库。默认为 false。 如果 SELECT 查询是在一个显式的事务块中,replicate_select 和 load_balance_mode 将影响复制的工作模式。以下为具体的细节。
如果在包含 SERIAL 类型的表中做复制, SERIAL 列的值在不同后台间可能不同。这个问题可以通过显式的锁表解决(当然,事务的并发性将被严重退化)。为了达到这个目的,必须做以下的改变:
INSERT INTO ... BEGIN; LOCK TABLE ... INSERT INTO ... COMMIT;
当
insert_lock
为 true 时,pgpool-II 自动在每次执行 INSERT 时添加以上的查询(如果已经在事务中,它只是简单地添加 LOCK TABLE ... )。
pgpool-II 2.2 或更高的版本中,可以自动探测是否表拥有 SERIAL 类型的列,所以如果没有 SERIAL 类型的列,则将不会锁表。 pgpool-II 3.0 系列直到 3.0.4 为止针对串行的关系使用一个行锁,而不是表锁。这使在 VACUUM(包括 autovacuum)时的锁冲突最小。但这会导致另一个问题。如果发生了嵌套事务,对串行的关系使用行所会导致 PostgreSQL 的内部错误(确切地说,保存事务状态的 pg_clog 会发生访问错误)。为了避免这个问题,PostgreSQL 核心开发者决定禁止对串行的关系加锁,当然这也会让 pgpool-II 无法工作("修复"后的 PostgreSQL 版本为 9.0.5, 8.4.9, 8.3.16 和 8.2.22)。 由于新版的 PostgreSQL 不允许对串行的关系加锁,pgpool-II 3.0.5 或更新的版本针对 pgpool_catalog.insert_lock 使用行锁。所以需要预先在通过 pgpool-II 访问的数据库中建立 insert_lock 表。详细内容请参考 建立 insert_lock 表 。如果不存在 insert_lock 表,pgpool-II 将锁定插入的目标表。这种行为和 pgpool-II 2.2 和 2.3 系列相同。如果你希望使用与旧版本兼容的 insert_lock,你可以在配置脚本中指定锁定模式。详细内容请参考 configure 。 你也许需要更好(针对每个事务)的控制手段:
insert_lock
为 true,并添加
/*NO INSERT LOCK*/
代码到你不想要表锁的 INSERT 语句的开始位置。
insert_lock
为 false,并添加
/*INSERT LOCK*/
到你需要表锁的 INSERT 语句的开始位置。
insert_lock
被启用,则(通过 pgpool-II 运行的) PostgreSQL 8.0 的事务、权限、规则和 alter_table 的回归测试会失败。原因是 pgpool-II 会尝试 LOCK 这些规则测试的 VIEW ,并产生以下的错误消息:
! ERROR: current transaction is aborted, commands ignored until
end of transaction block
例如,事务测试尝试 INSERT 到一个不存在的表,而 pgpool-II 导致 PostgreSQL 在这之前请求锁。事务将被终止,而之后的 INSERT 语句会产生以上的错误消息。
类似于 client_idle_limit 但是只在恢复的第二阶段生效。从执行最后一个查询后空闲到 client_idle_limit_in_recovery 秒的客户端将被断开连接。 这对避免 pgpool 的恢复被懒客户端扰乱或者客户机和 pgpool 之间的 TCP/IP 连接被意外断开(例如网线断开)非常有用。如果设置为 -1 ,则立即断开客户端连接。 client_idle_limit_in_recovery 的默认值为 0,表示本功能不启用。
如果你的客户端非常繁忙,则无论你将 client_idle_limit_in_recovery 设置为多少 pgpool-II 都无法进入恢复的第二阶段。在这种情况下, 你可以设置 client_idle_limit_in_recovery 为 -1 因而 pgpool-II 在进入第二阶段前立即断开这些繁忙的客户端的连接。 如果你改变了 client_idle_limit_in_recovery 你需要重新加载 pgpool.conf 。
复制模式中的特有错误
在复制模式中,如果 pgpool 发现 INSERT,UPDATE 和 DELETE 生效的行数不同,如果 failover_if_affected_tuples_mismatch 被设置为 false,则 pgpool 将发送错误的 SQL 语句到所有的数据库节点来取消当前当前事务(如果为 false 则发生退化)。 在这种情况下,你将在客户端终端中看到以下错误信息: =# UPDATE t SET a = a + 1; ERROR: pgpool detected difference of the number of update tuples Possible last query was: "update t1 set i = 1;" HINT: check data consistency between master and other db node 你将在 PostgreSQL 的日志中看到更新的行数(在本例中,数据库节点 0 更新了 0 行而数据库节点 1 更新了 1 行)。 2010-07-22 13:23:25 LOG: pid 5490: SimpleForwardToFrontend: Number of affected tuples are: 0 1 2010-07-22 13:23:25 LOG: pid 5490: ReadyForQuery: Degenerate backends: 1 2010-07-22 13:23:25 LOG: pid 5490: ReadyForQuery: Number of affected tuples are: 0 1
本模式用于使用其他负责完成实际的数据复制的主/备复制软件(类似于 Slong-I 和 基于流复制)来连接 pgpool-II。数据库节点的信息(如果你需要在线恢复功能,backend_hostname、backend_port、backend_weight、backend_flag 和 backend_data_directory )必须被设置,和复制模式中的方法相同。另外,还需要设置
master_slave_mode
和
load_balance_mode
为 true。pgpool-II 将发送需要复制的查询到主数据库,并在必要时将其他的查询将被负载均衡。不能被负载均衡而发送到主数据库的查询当然也是受负载均衡逻辑控制的。
在主/备模式中,对于临时表的 DDL 和 DML 操作只能在主节点上被执行。SELECT 也可以被强制在主节点上执行,但这需要你在 SELECT 语句前添加一个 /*NO LOAD BALANCE*/ 注释。
在主/备模式中,
replication_mode
必须被设置为 false ,并且
master_slave_mode
为 true。
主/备模式有一个“master_slave_sub mode”。默认值为 'slony',用于 Slony-I。你也可以设置它为 'stream',它在你想使用 PostgreSQL 内置的复制系统(基于流复制)时被设置。用于 Slony-I 子模式的示例配置文件为 pgpool.conf.sample-master-slave,用于基于流复制的子模式的示例文件为 sub-module is pgpool.conf.sample-stream。 修改以上任何参数都需要重新启动 pgpool-II。 在主/备模式中,你可以通过设置 white_function_list 和 black_function_list 来控制负载均衡。参考 white_function_list 获得详细信息。
本模式实现了查询的并行执行。表可以被分割,数据分布在每个节点中。而且,复制和负载均衡功能也可以同时使用。在并行模式中,pgpool.conf 中的 replication_mode 和 load_balance_mode 被设置为 ture,master_slave 被设置为 false,parallel_mode 被设置为 false。当你改变这些参数后,需要重启 pgpool-II。
如果想使用并行模式,System DB 需要被正确配置。System DB 包含存储在一个表中的,用于选择被分区的数据将被发送到的恰当后端程序的规则。
System DB 不一定要和 pgpool-II 在同一台主机上。System DB 的配置由
pgpool.conf
完成。
System DB 所在的主机名。给出空字符串('')表示 SystemDB 和 pgpool-II 在同一台主机,且将通过 UNIX 域套接字访问。
System DB 使用的端口号
分区规则和其他的信息将被定义到这里指定的数据库中。默认值为:
'pgpool'
。
分区规则和其他的信息将被定义到这里指定的模式中。默认值为:
'pgpool_catalog'
。
连接到 System DB 的用户名。
连接到 System DB 的密码,如果不需要密码,则设置为空字符串('')。
verify(1)
命令的
-CAfile
选项。
默认值为未设置,也就是不进行认证。如果本选项未设置但是
ssl_ca_cert_dir
被设置了,则认证过程依旧会发生。
verify(1)
命令的
-CApath
选项。
默认值为未设置,也就是不进行认证。如果本选项未设置但是
ssl_ca_cert
被设置了,则认证过程依旧会发生。
首先,需要建立
pgpool.conf
文件中指定的数据库和模式。可以在
$prefix/share/system_db.sql
找到一个示例脚本。如果你指定了不同的数据库名和模式,在脚本中相应地修改它们。
psql -f $prefix/share/system_db.sql pgpool
CREATE TABLE pgpool_catalog.dist_def(
dbname TEXT, -- database name
schema_name TEXT, -- schema name
table_name TEXT, -- table name
col_name TEXT NOT NULL CHECK (col_name = ANY (col_list)), -- partitioning key column name
col_list TEXT[] NOT NULL, -- names of table attributes
type_list TEXT[] NOT NULL, -- types of table attributes
dist_def_func TEXT NOT NULL, -- name of the partitioning rule function
PRIMARY KEY (dbname,schema_name,table_name)
分区规则函数(此处是 pgpool_catalog.dist_def_accounts )需要一个值作为分区的关键字列,并返回相应的DB节点ID。注意节点ID必须从0开始, 下面是为pgbench写的函数示例。 CREATE OR REPLACE FUNCTION pgpool_catalog.dist_def_accounts (val ANYELEMENT) RETURNS INTEGER AS ' SELECT CASE WHEN $1 >= 1 and $1 <= 30000 THEN 0 WHEN $1 > 30000 and $1 <= 60000 THEN 1 ELSE 2
Query cache 可以在 pgpool-II 的所有模式中使用。在 pgpool.conf 中启用它如下:
enable_query_cache = true 你还需要在 System DB 中创建下面的表: CREATE TABLE pgpool_catalog.query_cache ( hash TEXT, query TEXT, value bytea, dbname TEXT, create_time TIMESTAMP WITH TIME ZONE, PRIMARY KEY(hash, dbname) 然而,如果你不使用"pgpool_catalog"的话,你可能需要修改该语句中的 schema。 注意:当前的查询缓存的实现方法为在数据库中建立缓存数据。因此启用查询缓存可能会导致达不到最高的性能。即使相关的表被更新了,查询缓存的内容不会更新。你需要从缓存的表中删除缓存的数据或者通过 -c(删除缓存) 参数重启 pgpool-II。你可以在任何模式中使用基于内存的查询缓存。它不同于以上的查询缓存,因为基于内存的查询缓存会快很多,因为缓存存储于内存中。 另外,如果缓存事小了,你不需要重启 pgpool-II 因为相关的表已经得到更新了。
基于内存的缓存保存 SELECT 语句(以及它绑定的参数,如果 SELECT 是一个扩展的查询)以及对应的数据。 如果是相同的 SELECT 语句,则直接返回缓存的值。因为不再有 SQL 分析或者到 PostgreSQL 的调用,实际上它会非常快。 其他方面,它会比较慢,因为它增加了一些负载用于缓存。另外,当一个表被更新,pgpool 自动删除相关的表的缓存。 因此,在有很多更新的系统中,性能会降低。如果 cache_hit_ratio 低于 70%,建议你关闭基于内存的缓存。 基于内存的查询缓存通过监视 UPDATE,INSERT,ALTER TABLE一类的查询语句来自动删除缓存的数据。 但 pgpool-II 无法发现通过触发器、外键和 DROP TABLE CASCADE 产生的非显式的更新。 你可以通过配置 memqcache_expire 让 pgpool 在固定时间周期内自动删除缓存来避免这个问题, 你也可以通过配置 black_memqcache_table_list 来让 pgpool 的基于内存的缓存忽略指定的表。 如果你使用 pgpool-II 的多个实例来使用共享内存进行缓存,可能出现一个 pgpool 发现表被更新了因而删除了缓存,但另一个依旧使用旧的缓存。 对于这种情况,使用 memcached 是一个更好的策略。
-m s[mart]
--mode s[mart]
等待客户端断开连接,然后关闭(默认)
-m f[ast]
--mode f[ast]
并不等待客户端; 立即关闭
-m i[mmediate]
--mode i[mmediate]
等同于
'-m f'
pgpool 记录后端服务器的状态到 [logdir]/pgpool_status 文件中,当 pgpool 重启时,它读该文件并恢复后端服务器的状态。
这将避免可能由于下述原因造成的DB节点间的具有不同的数据:
pgpool-II 能够不需要重启而重新加载配置文件。 pgpool [-c][-f config_file][-a hba_file][-F pcp_config_file] reload -f config_file--config-file config-file指定 pgpool.conf -a hba_file--hba-file hba_file指定 pool_hba.conf -F pcp_config_file--pcp-password-file指定 pcp.conf 需要指出的是,一些配置项并不能通过重新加载来改变。新的修改后的配置将在新会话上生效。
SQL语句中的 "pool_status" 在以前的版本中已经存在,但是其它可选项在 3.0 中才出现。
"SHOW pool_status" 返回配置参数列表,包含参数的 name, value, 和 description。下面是返回结果的一个摘录: benchs2=# show pool_status; item | value | description -------------------------------+---------------------------------+------------------------------------------------------------------ listen_addresses | 127.0.0.1 | host name(s) or IP address(es) to listen to port | 9999 | pgpool accepting port number socket_dir | /tmp | pgpool socket directory num_init_children | 5 | # of children initially pre-forked child_life_time | 300 | if idle for this seconds, child exits
"SHOW pool_nodes" 返回所有配置节点的列表.它显示了节点的 id, hostname, port, status, 以及权重 weight (仅在使用负载均衡模式时有意义)。status 列可能的值可在 pcp_node_info reference 里获得解释。 benchs2=# show pool_nodes; id | hostname | port | status | lb_weight ------+-------------+------+--------+----------- 0 | 127.0.0.1 | 5432 | 2 | 0.5 1 | 192.168.1.7 | 5432 | 3 | 0.5 (2 lignes)
"SHOW pool_processes" 返回 pgpool-II 所有进程的信息,这些进程正等待连接或在处理一个连接。 结果有 6 列:
结果将一直返回 num_init_children 行。
benchs2=# show pool_processes; pool_pid | start_time | database | username | create_time | pool_counter ----------+---------------------+----------+-----------+---------------------+-------------- 8465 | 2010-08-14 08:35:40 | | | | 8466 | 2010-08-14 08:35:40 | benchs | guillaume | 2010-08-14 08:35:43 | 1 8467 | 2010-08-14 08:35:40 | | | | 8468 | 2010-08-14 08:35:40 | | | | 8469 | 2010-08-14 08:35:40 | | | | (5 lines)"SHOW pool_pools" 返回 pgpool-II 所处理的连接池列表,包含它们的 name, value, 和 description,下面是结果的一个摘录: 共 11 列:
结果将一直返回num_init_children*max_pool 行.
pool_pid | start_time | pool_id | backend_id | database | username | create_time | majorversion | minorversion | pool_counter | pool_backendpid | pool_connected ----------+---------------------+---------+------------+----------+-----------+---------------------+--------------+--------------+--------------+-----------------+---------------- 8465 | 2010-08-14 08:35:40 | 0 | 0 | | | | | | | | 8465 | 2010-08-14 08:35:40 | 1 | 0 | | | | | | | | 8465 | 2010-08-14 08:35:40 | 2 | 0 | | | | | | | | 8465 | 2010-08-14 08:35:40 | 3 | 0 | | | | | | | | 8466 | 2010-08-14 08:35:40 | 0 | 0 | benchs | guillaume | 2010-08-14 08:35:43 | 3 | 0 | 1 | 8473 | 1 8466 | 2010-08-14 08:35:40 | 1 | 0 | | | | | | | | 8466 | 2010-08-14 08:35:40 | 2 | 0 | | | | | | | | 8466 | 2010-08-14 08:35:40 | 3 | 0 | | | | | | | | 8467 | 2010-08-14 08:35:40 | 0 | 0 | | | | | | | | 8467 | 2010-08-14 08:35:40 | 1 | 0 | | | | | | | | 8467 | 2010-08-14 08:35:40 | 2 | 0 | | | | | | | | 8467 | 2010-08-14 08:35:40 | 3 | 0 | | | | | | | | 8468 | 2010-08-14 08:35:40 | 0 | 0 | | | | | | | | 8468 | 2010-08-14 08:35:40 | 1 | 0 | | | | | | | | 8468 | 2010-08-14 08:35:40 | 2 | 0 | | | | | | | | 8468 | 2010-08-14 08:35:40 | 3 | 0 | | | | | | | | 8469 | 2010-08-14 08:35:40 | 0 | 0 | | | | | | | | 8469 | 2010-08-14 08:35:40 | 1 | 0 | | | | | | | | 8469 | 2010-08-14 08:35:40 | 2 | 0 | | | | | | | | 8469 | 2010-08-14 08:35:40 | 3 | 0 | | | | | | | | (20 lines)"SHOW pool_version" 将显示包含 pgpool-II 版本号的一个字符串。下面是一个示例:
benchs2=# show pool_version; pool_version ------------------------ 3.0-dev (umiyameboshi) (1 line)"SHOW pool_cache" 显示启用 on memory query cache 时缓存的存储统计。以下为一个示例: test=# \x Expanded display is on. test=# show pool_cache; show pool_cache; -[ RECORD 1 ]---------------+--------- num_cache_hits | 891703 num_selects | 99995 cache_hit_ratio | 0.90 num_hash_entries | 131072 used_hash_entries | 99992 num_cache_entries | 99992 used_cache_enrties_size | 12482600 free_cache_entries_size | 54626264 fragment_cache_entries_size | 0
V3.1 - 然而它可能在转换执行完 前 返回,这样可能会导致在线恢复过程的失败。Pgpool-II提供了一个更加安全的称之为"pgpool_switch_xlog"的函数,该函数等待一直到事务日志转换实际被完成后。pgpool_switch_xlog 在 安装 C 函数 小节过程执行时被安装。 下面是示例脚本。 #! /bin/sh # Online recovery 2nd stage script datadir=$1 # master dabatase cluster DEST=$2 # hostname of the DB node to be recovered DESTDIR=$3 # database cluster of the DB node to be recovered port=5432 # PostgreSQL port number archdir=/data/archive_log # archive log directory # Force to flush current value of sequences to xlog psql -p $port -t -c 'SELECT datname FROM pg_database WHERE NOT datistemplate AND datallowconn' template1| while read i if [ "$i" != "" ];then psql -p $port -c "SELECT setval(oid, nextval(oid)) FROM pg_class WHERE relkind = 'S'" $i psql -p $port -c "SELECT pgpool_switch_xlog('$archdir')" template1 % pgpool_remote_start remote_host remote_datadir remote_host: Hostname of a recovery target. remote_datadir: Database cluster path of a recovery target. 在该示例脚本中,我们通过 ssh 启动 postmaster 进程。所以如果你想要它能够运行,你需要提供不需要密码输入的 ssh 连接。 如果你使用PITR进行恢复,你需要部署一个库备份。PostgreSQL 将自动启动一个 PITR 恢复,然后它开始接受连接。 #! /bin/sh DEST=$1 DESTDIR=$2 PGCTL=/usr/local/pgsql/bin/pg_ctl # Deploy a base backup ssh -T $DEST 'cd /data/; tar zxf pgsql.tar.gz' 2>/dev/null 1>/dev/null < /dev/null # Startup PostgreSQL server ssh -T $DEST $PGCTL -w -D $DESTDIR start 2>/dev/null 1>/dev/null < /dev/null &
不保证使用依赖上下文的机制所产生的数据(如 random number, transaction ID, OID, SERIAL, sequence),都会被在多个后台服务器上被正确的复制。
对于SERIAL,启用insert_lock在数据复制中很有用。insert_lock 还有助于 SELECT setval() 和 SELECT nextval()。
在 pgpool-II 2.3 或更高版本中,使用 CURRENT_TIMESTAMP,CURRENT_DATE, now()的 INSERT/UPDATE 将会被正确的复制。INSERT/UPDATE 使用 CURRENT_TIMESTAMP, CURRENT_DATE, now() 作为表的默认值时,也将会正确的复制。这通过执行时把这些函数替换成从master节点上获取的常量值来完成。然而仍有一些限制:
pgpool-II 3.1 后更高版本能够正确的处理这些情况。这样"d1"将会把明天(CURRENT_DATE + 1)作为默认值。然而当扩展的协议(例如在JDBC, PHP PDO中使用的)或者 PREPARE 被使用时,这个改进并不适用。 请注意如果列类型不是临时的,重写并不会被执行,这儿有个例子: foo bigint default (date_part('epoch'::text,('now'::text)::timestamp(3) with time zone) * (1000)::double precision)
如果你在使用 8.3 或更高的版本 PostgreSQL ,并且在 reset_query_list 中指定 DISCARD ALL,那么将在会话的末尾处删除
CREATE TEMP TABLE
创建的表。
对于8.2.x或更早的版本,退出会话时并不会删除
CREATE TEMP TABLE
创建的表。这是由于连接池的原因,从 PostgreSQL 后台的视角来看,要保持 session 处于活动状态。为避免这一点,你必须通过发出
DROP TABLE
命令显式的删除该临时表,或在事务块中使用
CREATE TEMP TABLE ... ON COMMIT DROP
语句。
下面是不能被 pgpool-II 处理的查询。
你不能使用
DEFAULT
作为分区关键字列(partitioning key column)。例如如果表t中的列x是分区关键字列,
INSERT INTO t(x) VALUES (DEFAULT);
这将是无效的。而且该值也不能使用函数。
INSERT INTO t(x) VALUES (func());
INSERT的分区值只能是常量值。
SELECT INTO
和
INSERT INTO ... SELECT
也不被支持。
如果分区关键字列值被更新,后台数据库的数据一致性可能会丢失。pgpool-II 并不重新分区更新的数据。
如果约束被违反时一个查询在后台数据库中引起的了一个错误,一个事务有可能不能够被回滚。
如果在
WHERE
从句中一个函数被调用,该查询可能不能够被正确的执行。例如:
UPDATE branches set bid = 100 where bid = (select max(bid) from beances);
如果在
WHERE
从句中一个函数被调用,该查询可能不能够被正确的执行。例如:
SELECT * FROM branches where bid = (select max(bid) from beances) FOR UPDATE;
COPY BINARY
不被支持。从文件中拷贝也不被支持。只有
COPY FROM STDIN
和
COPY TO STDOUT
被支持。
为更新分区规则,pgpool-II 必须重启以从 System DB 读取它们。
一个事务块里面执行的
SELECT
语句将被在一个单独的事务中执行,这有个示例:
BEGIN;
INSERT INTO t(a) VALUES (1);
SELECT * FROM t ORDER BY a;
像上面的
JOIN
将在后台数据库中执行,然后由每个后台数据库返回的结果进行合并。跨节点的 Views 和 Rules 不能够被创建。然而若连接的表的数据都在同一个节点中,一个 VIEW 能够被创建。该VIEW需要在 pgpool_catalog.dist_def 中注册。一个 col_name 和 一个 dist_def_func 也必须进行注册,它们当在视图上执行插入操作时被使用。
同样的函数定义将在所有的后台数据库中被创建。函数内不能执行跨节点连接(Join),不能访问其它节点的数据。
JDBC驱动等等所使用的扩展的查询协议不被支持。必须使用简单的查询协议。这意味着你不能使用prepared statement。
自然连接(Natural Join)不被支持。必须使用"ON join condition" 或 "USING (join_column)"。
USING CLAUSE 通过查询重写过程被转换为 ON CLAUSE。这样,当在目标列表中含有"*"时,连接的列会出现两次。 这儿有个示例: =# SELECT * FROM t1 JOIN t2 USING(id); id | t | t ----+-----+------- 1 | 1st | first (1 row) 在query rewrite过程中"USING"被转换成"ON"。这样下面是生效的重写结果: =# SELECT * FROM t1 JOIN t2 ON t1.id = t2.id; id | t | id | t ----+-----+----+------- 1 | 1st | 1 | first (1 row) 注意列"t"被重复。
pgpool-II 不会在不同的多字节字符间进行转换。client, backend 以及 System DB 之间的编码必须相同。
跨越多个后台数据库的死锁不能够被检测。例如: (tellers table is partitioned using the following rule) tid <= 10 --> node 0 tid >= 10 --> node 1 A) BEGIN; B) BEGIN; A) SELECT * FROM tellers WHERE tid = 11 FOR UPDATE; B) SELECT * FROM tellers WHERE tid = 1 FOR UPDATE; A) SELECT * FROM tellers WHERE tid = 1 FOR UPDATE; B) SELECT * FROM tellers WHERE tid = 11 FOR UPDATE; 在上述情况下,单个的节点不能探测到死锁,这样pgpool-II将会无限期的等待响应。该现象可出现在任何获取行级别锁(row level lock)的query中。
而且,如果一个节点上出现了一个死锁,每个节点的事务状态将不再具有一致性。这样如果死锁被探测到 pgpool-II 将终止该进程。 pool_read_kind: kind does not match between master(84) slot[1] (69)
schema 中非 public 下的对象必须使用完整名字,如: schema.object 当路径设置如下时,pgpool-II 不能找到正确的 schema: set search_path = xxx 且 schema 名在 query 中被省略。
仅可在一个分区规则中定义一个分区关键字列。如同'x or y'的条件式不被支持。
libpq
被链接。libpq版本必须是3.0。使用2.0版本的libpq编译pgpool-II将会失败。而且System DB 必须是 PostgreSQL 7.4 或更高版本。
当前, 查询缓存 必须被手动删除。 但这不影响 基于内存的查询缓存 。基于内存的查询缓存会自动清除无效的缓存。
PCP 命令是UNIX命令,通过网络操作pgpool-II。
pcp_node_count 获取节点数量 pcp_node_info 获取节点信息 pcp_proc_count 获取进程列表 pcp_proc_info 获取进程信息 pcp_pool_status V3.1 - 获取 pgpool.conf 中的参数 pcp_systemdb_info 获取 System DB 信息 pcp_detach_node 从 pgpool-II 脱离一个节点 pcp_attach_node 给 pgpool-II 关联一个节点 pcp_promote_node V3.1 - 给 pgpool-II 提升一个新的master节点 pcp_stop_pgpool 停止 pgpool-II对于所有的PCP命令有5个常用的参数。它们给出了pgpool-II的信息和认证。对于有些命令必须需要多余的参数。 例如) $ pcp_node_count 10 localhost 9898 postgres hogehoge 第1个 argument - 以秒为单位的等待时间. 如果pgpool-II在这个数量的秒内没有响应,PCP将断开连接。 第2个 argument - pgpool-II的主机名 第3个 argument - PCP 端口号 第4个 argument - PCP 用户名 第5个 argument - PCP 密码
PCP的用户名和密码必须在
$prefix/etc
目录中的
pcp.conf
中声明。
启动pgpool-II时
-F
选项可被用来指定
pcp.conf
所处的别的位置。当传递给PCP命令时,并不需要以md5格式的密码。
所有的PCP命令把结果显示在标准输出中。
pgpool.conf
中定义的所有的节点总数。它并不区别节点状态,例如attached/detached。所有节点都被算进去。
指定一个无效的节点 ID 将会导致一个退出状态为 12 的错误,而且 BackendError 将被显示。
指定一个无效的节点 ID 将会导致一个退出状态为 12 的错误,而且 BackendError 将被显示。
* 当前,快速和立即模式没有区别。pgpool-II 终止所有的进程无论是否还有客户端连接到后端服务器。
PCP 命令正确退出时状态为0.若由错误出现,将会具有如下的错误状态。 UNKNOWNERR 1 Unknown Error (should not occur) EOFERR 2 EOF Error NOMEMERR 3 Memory shortage READERR 4 Error while reading from the server WRITEERR 5 Error while writing to the server TIMEOUTERR 6 Timeout INVALERR 7 Argument(s) to the PCP command was invalid CONNERR 8 Server connection error NOCONNERR 9 No connection exists SOCKERR 10 Socket error HOSTERR 11 Hostname resolution error BACKENDERR 12 PCP process error on the server (specifying an invalid ID, etc.) AUTHERR 13 Authorization failure
由于 TARGETLIST 和 WHERE 从句导致执行状态的改变
在一个基本的查询中,执行状态来自于 FROM 语句。然而,如果存在一个T ARGETLIST,WHERE 语句的执行状态能够以如下情况进行改变:若一个列不存在于一个表中时,也可以在一个查询中使用。例如在下面的子查询中: SELECT * FROM L1-table WHERE L1-table.col1 IN (SELECT * FROM P1-table WHERE P1-table.col = L1-table.col1); 该子查询从L1-table表中引用了L1-table.col1,含子查询的 WHERE 语句的执行状态为S。
由于 GROUP BY, HAVING, ORDER BY 和 LIMIT/OFFSET 导致执行状态的改变
执行状态是'P'的 WHERE 语句,若还存在GROUP BY, HAVING, ORDER BY 语句, 或 LIMIT/OFFSET 断言时,状态改为'S'。没有 GROUP BY 的查询从 WHERE 语句获取状态。类似的方法,若没有 HAVING 语句,将使用 GROUP BY 语句的执行状态。ORDER BY 语句和 LIMIT/OFFSET 断言具有类似的行为。当使用 UNION, EXTRACT, 及 INTERSECT 时
UNION, EXTRACT, 及 INTERSECT 查询的状态依赖于最终左侧和右侧 SELECT 语句的状态。若左右侧的状态都是L,组合的状态是L。若二者都是P,且查询是 UNION ALL,那么组合的状态是P。其它情况最终结果都是S。获取 SELECT 的最终执行状态
如果 SELECT 中所有语句都具有状态L,那么最终的执行状态是L。同样规则使用P。对于任何其它的组合最终状态是S。如果状态是L,若 loadbalance_mode 为 true 时负载被分布在不同的节点中,否则只被发送到 MASTER 节点上。对于状态P,将使用并行执行引擎进行并行处理。对于S,将会进入下面讲述的查询重写。在该示例中 FROM 和 WHERE 语句以及 TARGETLIST 被以并行模式执行。这不是一个真正的重写查询,只是因为想提供一个示例。 这儿有另一个例子: SELECT L1-table.col FROM L1-table WHERE L1-table.col % 2 = 0 AND L1-table.col IN (SELECT P1-table FROM P1-table) ; 在该示例中,FROM 和 WHERE 语句以及 TARGETLIST 都具有状态L。因为子查询是P状态,查询本身也为S状态。这样重写为如下: SELECT L1-table.col FROM dblink(SELECT loadbalance(SELECT L1-table.col FROM L1-table WHERE L1-table.col % 2 = 0 AND TRUE)) WHERE L1-table.col %2 = 0 AND L1-table.col IN SELECT P1-Table FROM dblink(select pool_parallel(SELECT P1-table FROM P1-table))
pool_loadbalance 是一个函数,负责分发查询到任一个节点。
首先,我们看看 pgpool-II 为重写都做了那些事情。
该查询的 FROM 语句具有P状态且 TARGETLIST 含有count(*),于是重写如下: select count(*) from P1-table; -> rewrite SELECT sum(pool_c$1) as count dblink(select pool_parallel('select count(*) from P1-table')) AS pool_$1g (pool_c$1 bigint);
在如下的条件下查询就会重写为上面类似的形式。
下面是一个相对于执行状态的查询性能的粗略估计: 执行状态性能 L一个节点时除去pgpool-II的开销,没有性能损失,因为根本就没有并行查询 P并行处理是很快的,特别针对顺序扫描。由于扫描大表变成在几个节点上分布式存在的小表上进行并行扫描,故很容易获得加速比。 S当聚集函数可在并行方式被重写时,它们很快。 pgpool-II入门教程 已发布。
听话的板栗 · pgpool-II 用户手册 1 月前 |
大气的针织衫 · pgpool-II user manual 1 年前 |
坚强的吐司 · pgpool-II 用户手册 1 年前 |
纯真的柑橘 · 輸入資料流成員函式 | Microsoft Learn 3 月前 |