Rails 4.2 Postgres 9.4.4 statement_timeout不起作用

时间:2018-11-05 19:00:44

标签: ruby-on-rails postgresql

我正在尝试设置一个statement_timeout。我试过像这样在database.yml文件中进行设置

variables:
  statement_timeout: 1000

还有这个

ActiveRecord::Base.connection.execute("SET statement_timeout = 1000")

经过测试

ActiveRecord::Base.connection.execute("select pg_sleep(4)")

它们都没有任何作用。

我正在本地运行postgres 10,并且statement_timeouts可以正常工作。但是在运行Postgres 9.4.4的服务器上,它什么也没做。

我已检查Postgres' doc for 9.4,并且statement_timeout可用。任何人都可以露面吗?

1 个答案:

答案 0 :(得分:1)

我无法使用:Postgresql 9.4.26在本地复制此问题。但是分享我的尝试和有关服务器问题的一些想法可能会很有用。 这是我尝试过的方法(有用的一点可能是从rails验证PG版本的查询):

# Confirming I am executing against 9.4.x PG:

irb(main):002:0> ActiveRecord::Base.connection.execute("select version()")
   (10.8ms)  select version()
=> #<PG::Result:0x00007ff74782e060 status=PGRES_TUPLES_OK ntuples=1 nfields=1 cmd_tuples=1>
irb(main):003:0> _.first
=> {"version"=>"PostgreSQL 9.4.26 on x86_64-apple-darwin18.7.0, compiled by Apple clang version 11.0.0 (clang-1100.0.33.17), 64-bit"}


# Set timeout:

irb(main):004:0> ActiveRecord::Base.connection.execute("SET statement_timeout = 1000")
   (0.4ms)  SET statement_timeout = 1000
=> #<PG::Result:0x00007ff7720a3d88 status=PGRES_COMMAND_OK ntuples=0 nfields=0 cmd_tuples=0>


# Confirm it works - it is ~1s and also stacktrace is pretty explicit about it:

irb(main):005:0> ActiveRecord::Base.connection.execute("select pg_sleep(4)")
   (1071.2ms)  select pg_sleep(4)
.... (stacktrace hidden)
ActiveRecord::StatementInvalid (PG::QueryCanceled: ERROR:  canceling statement due to statement timeout)
: select pg_sleep(4)

这是尝试的方法

由于此问题仅在服务器上发生,并且由于statement_timeout在其他次要版本和本地上均可使用,因此想到的一件事是缺少从尝试更新statement_timeout的特权。也许用于建立数据库连接的Rails pg登录名不允许更新该设置。 最好的办法是通过服务器上的Rails控制台来验证:

irb(main):004:0> ActiveRecord::Base.connection.execute("SET statement_timeout = 1000")
irb(main):004:0> irb(main):003:0> ActiveRecord::Base.connection.execute("show statement_timeout").first
   (0.2ms)  show statement_timeout
=> {"statement_timeout"=>"1s"}

或者,可以直接通过psql控制台对其进行检查(某些部署也允许这样做):

psql myserveruser # if this was heroku's pg: heroku pg:psql

postgres=# set statement_timeout = 1000;
SET
postgres=# select pg_sleep(4);
ERROR:  canceling statement due to statement timeout
Time: 1068.067 ms (00:01.068)

其他要记住的事情(摘自https://dba.stackexchange.com/a/83035/90903):

statement_timeout的工作方式,时间从 服务器从客户端接收到新命令...

如果一个函数执行SET statement_timeout = 100;它只会在 来自客户端的下一个命令。