我有一个使用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"
但是有时,在解析/绑定(bind)/执行步骤之间,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
据我了解,由于该查询是未命名的,因此如果在执行该未命名查询之前在该数据库 session 期间出现另一个查询,则Postgres会丢弃该查询。因此,由于PGPool有时会在解析/绑定(bind)/执行步骤之间发出这些额外的查询,因此导致查询被丢弃。
我的第一个想法是,也许我的Java应用程序不需要为每个查询发送解析/绑定(bind)/执行语句。但是,自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时运行。我不得不为了使用PGPool而不得不退回到JDBC版本2协议(protocol)这一事实困扰着我。 最佳答案
我找到了解决该问题的方法。通过将protocolVersion = 2放置在JDBC URL中,它基本上告诉Postgres JDBC驱动程序不要使用服务器端准备好的语句。这允许我的应用程序在数据库前面使用PGPool II时运行。我不得不为了使用PGPool而不得不退回到JDBC版本2协议(protocol)这一事实困扰着我。