Rails 3.2频繁postgres准备语句已经存在错误

Eug*_*eia 16 postgresql ruby-on-rails heroku prepared-statement ruby-on-rails-3.2

我一直在挖堆stackoverflow试图找到其他谁得到这些准备好的语句已存在错误.

在大多数情况下,使用after/before fork正确配置unicorn可以解决这些问题.

但是在我的情况下,我们仍然会遇到错误:

ActiveRecord::StatementInvalid: PG::Error: ERROR: prepared statement "a495" already exists: INSERT INTO "user_logins" ("account_id", "created_at", "ip_address", "user_agent", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id"
Run Code Online (Sandbox Code Playgroud)

这个错误在我们的应用程序的不同区域被抛出但似乎总是具有相同的语句号'a495'.

我们在轨道3.2.17,使用postgres,我们在heroku.

我真的不知道为什么会这样,但它现在开始更频繁地发生.

任何帮助将不胜感激.

在rails stack跟踪中,此错误将在.prepare调用中抛出.我很困惑,因为它检查了语句集合中的sql密钥.如果它不存在它准备新的....但是当试图准备它时,它抛出错误.

def prepare_statement(sql)
  sql_key = sql_key(sql)
  unless @statements.key? sql_key
    nextkey = @statements.next_key
    @connection.prepare nextkey, sql
    @statements[sql_key] = nextkey
  end
  @statements[sql_key]
end
Run Code Online (Sandbox Code Playgroud)

qua*_*ome 32

我们遇到了同样的问题,并做了非常彻底的调查.我们得出结论,在我们的例子中,这个错误是由于Rack::Timeout在新的语句已经创建之后但在Rails端更新计数器之前偶尔中断代码执行引起的.接下来准备好的语句然后尝试使用相同的名称(例如a494),并发生冲突.

我的信念是Rails没有正确实现准备好的语句.他们应该使用GUID,而不是使用增加的计数器(a001,a002...).这样,上述竞争条件不会成为问题.

我们没有找到解决方法.提高应用程序的性能,增加应用程序的窗口Rack::Timeout,使这个问题几乎绝迹,但它仍然不时发生.

  • 门票:https://github.com/rails/rails/pull/17607和https://github.com/rails/rails/pull/25827 (3认同)

cat*_*sby 4

这通常不是 Postgres 问题,而是在 Unicorn 等中共享数据库连接的问题:

  • 另请注意,Rails 4.1 在 database.ml 上有这样的设置:按照 [Rails 指南](http://edgeguides.rubyonrails.org/configuring.html#connection-preference) `prepared_statements: false` (3认同)