针对PGPool II的Java查询导致“未命名的预准备语句不存在”错误

时间:2012-03-15 17:29:21

标签: java postgresql jdbc postgresql-9.1 pgpool

我有一个使用Postgres数据库的Java应用程序,我正在尝试引入PGPool以扩展我的数据库。我遇到了Postgres抛出以下错误的问题:unnamed prepared statement does not exist。在启动Postgres上的日志记录后,我发现我的应用程序执行的每个select语句都会发生以下事情:

EDTLOG:  00000: duration: 7.585 ms  parse <unnamed>: "my select statement here"
EDTLOG:  00000: duration: 0.088 ms  bind <unnamed>: "my select statement here"
EDTLOG:  00000: duration: 79.014 ms  execute <unnamed>: "my select statement here"

但有时候,在解析/绑定/执行步骤之间PGPool会执行一些额外的查询,所以日志看起来像这样:

EDTLOG:  00000: duration: 7.585 ms  parse <unnamed>: "my select statement here"
EDTLOG:  00000: duration: 0.088 ms  bind <unnamed>: "my select statement here"
EDTLOG:  00000: duration: 0.328 ms  statement: SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.relname = 'my_table' AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog'
EDTLOG:  00000: duration: 79.014 ms  execute <unnamed>: "my select statement here"
EDTERROR:  26000: unnamed prepared statement does not exist
EDTLOG:  00000: duration: 0.022 ms  parse S_2: ROLLBACK
EDTLOG:  00000: duration: 0.005 ms  bind S_2: ROLLBACK
EDTLOG:  00000: duration: 0.008 ms  execute S_2: ROLLBACK

据我所知,因为查询是未命名的,所以如果在执行未命名查询之前在该数据库会话期间出现另一个查询,它将被Postgres抛弃。因为PGPool有时会在解析/绑定/执行步骤之间发出这些额外的查询,导致查询被丢弃。

我的第一个想法是,我的Java应用程序可能不需要为每个查询发送parse / bind / execute语句。但看起来这是自JDBC版本3和Postgres 7.4 http://jdbc.postgresql.org/documentation/head/server-prepare.html以来Postgres JDBC驱动程序的默认行为。我想我可以尝试完全禁用服务器端预处理语句,但文档没有指定如何做到这一点,我不确定这是我想要做的事情。

我的第二个想法是让PGPool II停止发送那些元数据查询。由于我只是想使用PGPool作为负载均衡器,我真的不明白为什么它需要知道我的表元数据的所有内容。我在PGPool源的is_system_catalog方法中跟踪了执行这些查询的代码:https://github.com/iakio/pgpool-II/blob/master/pool_select_walker.c#L256似乎PGPool想知道我的表关系是出于某种原因,不幸的是我没有看到任何方法禁用该行为。

非常感谢任何有关如何解决此问题的见解。

有关我的环境的一些信息:

JDBC Driver: postgresql-9.1-901.jdbc4.jar
Java version "1.6.0_31"
Spring 3.1 managed JPA 
Hibernate 3.5
Postgres 9.1

更新 我找到了解决这个问题的方法。通过将protocolVersion=2放在JDBC URL中,它基本上告诉Postgres JDBC驱动程序不要使用服务器端预处理语句。这允许我的应用程序在我的数据库前使用PGPool II时运行。令我感到困扰的是,我必须回到JDBC版本2协议,只是为了使用PGPool。

2 个答案:

答案 0 :(得分:3)

我找到了解决问题的方法。通过在JDBC URL中放置protocolVersion = 2,它基本上告诉Postgres JDBC驱动程序不要使用服务器端预处理语句。这允许我的应用程序在我的数据库前使用PGPool II时运行。令我感到困扰的是,我必须回到JDBC版本2协议,只是为了使用PGPool。

答案 1 :(得分:-1)

是什么,如果你说出准备好的陈述?

另一个问题出现了:如果你不需要,你为什么要使用准备好的陈述?

您可以轻松地针对jdbc驱动程序发出“正常”语句...