准备好的声明不存在

时间:2013-11-22 17:07:17

标签: postgresql sinatra pgbouncer

目前运行一个简单的sinatra应用程序,使用乘客,并使用pgbouncer连接池到与应用程序在同一服务器上的数据库。目前我间歇性地得到PG错误,准备好的声明“a \ d”不存在。

A PG::Error occurred in #: 
ERROR: prepared statement "a2" does not exist 

错误之前执行的ruby代码

def self.get_ownership_record(id, key)
  self.where("user_id=? AND key=?", id, key ).first 
end

pgbouncer config

; #########################################################
; ############# SECTION HEADER [DATABASES] ################
; #########################################################

[databases]

fakedatabase=fake

[pgbouncer]

; ----- Generic Settings --------------------------
; -------------------------------------------------
logfile=/opt/local/var/log/pgbouncer/pgbouncer.log
pidfile=/opt/local/var/run/pgbouncer/pgbouncer.pid
listen_addr=*
listen_port=5444

; unix_socket_dir=/tmp
user=_webuser
auth_file=/Users/Shared/data/global/pg_auth
auth_type=trust
pool_mode=transaction
; max_client_conn=100
; default_pool_size=20
; reserve_pool_size=0
; reserve_pool_timeout=5
; server_round_robin=0

; ----- Log Settings ------------------------------
; -------------------------------------------------
; syslog=0
; syslog_ident=pgbouncer
; syslog_facility=daemon
; log_connections=1
; log_disconnections=1
; log_pooler_errors=1

; ----- Console Access Control --------------------
; -------------------------------------------------
admin_users=admin,nagios
; -------------------------------------------------
; server_reset_query=DISCARD ALL;
 server_check_delay=0
 server_check_query=SELECT 1;
; server_lifetime=3600
; server_idle_timeout=600
; server_connect_timeout=600
; server_login_retry=15

我唯一的解决方案是关闭准备好的陈述吗?

的database.yml

production:
  adapter: postgresql
  database: fakedatabase
  username: admin
  host: localhost
  port: 5444
  reconnect: true
  prepared_statements: false

修改

我已更新pgbouncer.ini以使用会话池

pool_mode=session

并取消注释

server_reset_query=DISCARD ALL;

我仍然看似随机地得到涉及准备好的陈述的错误,但这一次

An ActiveRecord::StatementInvalid occurred in #: 

PG::Error: ERROR: bind message supplies 2 parameters, but prepared statement "a1" requires 0 

我在postgresql日志中打开了语句级别日志记录,如果可能的话会报告更多详细信息。

4 个答案:

答案 0 :(得分:2)

理查德·赫克斯顿建议,并经过一些试验和错误。

我的最终设置看起来像

database.yml

必须将prepared_statements设置为true

production:
  adapter: postgresql
  database: fakedatabase
  username: admin
  host: localhost
  port: 5444
  reconnect: true
  prepared_statements: true

pgbouncer.ini

必须取消注释server_reset_query=DISCARD ALL;

并设置pool_mode=session

; #########################################################
; ############# SECTION HEADER [DATABASES] ################
; #########################################################

[databases]

fakedatabase=fake

[pgbouncer]

; ----- Generic Settings --------------------------
; -------------------------------------------------
logfile=/opt/local/var/log/pgbouncer/pgbouncer.log
pidfile=/opt/local/var/run/pgbouncer/pgbouncer.pid
listen_addr=*
listen_port=5444

; unix_socket_dir=/tmp
user=_webuser
auth_file=/Users/Shared/data/global/pg_auth
auth_type=trust
pool_mode=session
; max_client_conn=100
; default_pool_size=20
; reserve_pool_size=0
; reserve_pool_timeout=5
; server_round_robin=0

; ----- Log Settings ------------------------------
; -------------------------------------------------
; syslog=0
; syslog_ident=pgbouncer
; syslog_facility=daemon
; log_connections=1
; log_disconnections=1
; log_pooler_errors=1

; ----- Console Access Control --------------------
; -------------------------------------------------
admin_users=admin,nagios
; -------------------------------------------------
server_reset_query=DISCARD ALL;
server_check_delay=0
server_check_query=SELECT 1;
; server_lifetime=3600
; server_idle_timeout=600
; server_connect_timeout=600
; server_login_retry=15

基本上允许使用默认服务器重置查询在会话池模式下准备语句。

答案 1 :(得分:1)

也许reading the FAQ会有所帮助?除非你有充分的理由不这样做,否则会话合并应该是明智的。

答案 2 :(得分:0)

您可以使用事务池,前提是您在同一事务中PREPAREEXECUTE准备好的查询(以避免pgBouncer在其间运行server_reset_query)。

答案 3 :(得分:0)

在我的情况下访问postgres目录并运行" DEALLOCATE ALL"解决问题。

如果你使用heroku,就像这样

> heroku pg:psql -a app_name
app_name::DATABASE=> DEALLOCATE ALL