Ruby on rails Rails 3.2频繁postgres准备语句已存在错误
我一直在stackoverflow周围挖掘,试图找到其他获得这些准备好的语句的人已经存在错误 在大多数情况下,使用after/befork正确配置unicorn可以解决这些问题 然而,在我的案例中,我们仍然会遇到这样的错误:Ruby on rails Rails 3.2频繁postgres准备语句已存在错误,ruby-on-rails,postgresql,heroku,ruby-on-rails-3.2,prepared-statement,Ruby On Rails,Postgresql,Heroku,Ruby On Rails 3.2,Prepared Statement,我一直在stackoverflow周围挖掘,试图找到其他获得这些准备好的语句的人已经存在错误 在大多数情况下,使用after/befork正确配置unicorn可以解决这些问题 然而,在我的案例中,我们仍然会遇到这样的错误: ActiveRecord::StatementInvalid: PG::Error: ERROR: prepared statement "a495" already exists: INSERT INTO "user_logins" ("account_id", "cre
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"
这个错误会在我们的应用程序的不同区域抛出,但似乎总是有相同的语句编号“a495”
我们在rails 3.2.17上,使用postgres,我们在heroku上
我真的不知道为什么会发生这种情况,但现在这种情况开始越来越频繁了
任何帮助都将不胜感激
在rails堆栈跟踪中,此错误将在.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
这通常不是Postgres的问题,而是在Unicorn中共享数据库连接的问题:
- 我们也遇到了同样的问题,并进行了非常彻底的调查。我们得出结论,在我们的例子中,这个错误是由
Rack::Timeout
引起的,在创建新语句之后,但在Rails端更新计数器之前,偶尔会中断代码执行。然后,下一个准备好的语句尝试使用相同的名称(例如,a494
),并发生冲突
我认为Rails没有正确地实现预先准备好的语句。他们不应该使用递增计数器(a001
,a002
,…),而应该使用guid。这样,上述比赛条件就不会成为问题
我们没有找到解决办法。提高应用程序的性能,并增加
Rack::Timeout
的窗口,使这个问题几乎消失,但它仍然时常发生 这是我对Heroku的解决方案,不幸的是,它有点牵扯其中。不过,从好的方面来看,当这个错误开始发生时,您不需要遭受100次错误通知。所需要的只是重新启动应用程序/dyno
该过程的基本要点是,当我们检测到一个ActiveRecord::StatementInvalid
异常,并且错误消息描述中包含“prepared statement”字样时,我们使用heroku的平台api
gem运行heroku restart
命令
platformapi
gem放入gem文件中,然后运行bundle安装
应用程序控制器(/app/controllers/application\u controller.rb):
class ApplicationController
就这样。希望这能有所帮助。在非Heroku PostgreSQL上,我会设置一个标识pid和会话的
log\u line\u前缀,启用log\u statement=all
,并查看日志。在Heroku,我不知道这是否可行。我们按照Heroku的建议配置了独角兽,所以我不确定从这个角度出发我们还能做些什么;这里有一个初始值设定项可以做到这一点:还要注意Rails 4.1在database.ml上有这样的设置:prepared_statements:false
根据@CharlesForcey关闭prepared statements实际上可以防止这个错误吗?这很有意义——我们也会遇到同样的问题(Rails 4/Heroku/Puma),我将寻找与超时的关联。谢谢。你用Rails开过票吗?它修好了吗?票:在经过几年可靠的服务后,这对我来说已经不起作用了
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::StatementInvalid do |exception|
# notify your error handler, or send an email, or whatever
# ...
if exception.message =~ /prepared statement/
restart_dyno
end
end
def restart_dyno
heroku = PlatformAPI.connect_oauth(ENV["HEROKU_API_KEY"])
heroku.dyno.restart(ENV["HEROKU_APP_NAME"], "web")
end
end