首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止一个繁琐的查询在Postgrex中超时?

如何防止一个繁琐的查询在Postgrex中超时?
EN

Stack Overflow用户
提问于 2019-07-08 22:37:22
回答 1查看 1.3K关注 0票数 3

我正在使用Postgrex运行查询并将结果加载到流中,如下所示:

代码语言:javascript
复制
{:ok, host_pid} = Postgrex.start_link(hostname: "somewhere.hostname.io", username: "myuser", password: "mypass", database: "mydb")

Postgrex.transaction(host_pid, fn(conn) ->
    # do query that takes 5 seconds
    # with timeout set to be really big
    query = Postgrex.prepare!(conn, "", "SELECT pg_sleep(5)", timeout: 50_000)
    stream = Postgrex.stream(conn, query)
    result_to_iodata = fn(%Postgrex.Result{rows: rows}) -> format_query_result(rows) end
    Enum.into(stream, File.stream!("eg"), result_to_iodata)
end)

但我得到了以下错误:

代码语言:javascript
复制
localhost$ mix run lib/MyPostgrexScript.exs 
** (DBConnection.ConnectionError) connection not available and request was dropped 
from queue after 2950ms. You can configure how long requests wait in the queue 
using :queue_target and :queue_interval. See DBConnection.start_link/2 for more information
    (db_connection) lib/db_connection.ex:836: DBConnection.transaction/3
    lib/MyPostgrexScript.exs:3: MyPostgrexModule.sleep/0
    (elixir) lib/code.ex:767: Code.require_file/2
    (mix) lib/mix/tasks/run.ex:147: Mix.Tasks.Run.run/5

由于我想要执行繁琐的查询,这肯定需要超过2950 my才能运行,所以我想知道如何配置Postgrex以让我的查询花费更多时间。我在https://hexdocs.pm/postgrex/Postgrex.html#transaction/3上读过关于https://hexdocs.pm/postgrex/Postgrex.html#transaction/3选项的文章,但是我不确定如何包含它,或者它是否是我想要的。

任何指导都是非常感谢的,谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-08 23:41:45

我在https://hexdocs.pm/postgrex/Postgrex.html#transaction/3上读到了:timeout选项,但我不确定如何包含它,

如下所示(参见最后一行):

代码语言:javascript
复制
Postgrex.transaction(
    host_pid,

    fn(conn) ->
        # do query that takes 5 seconds
        # with timeout set to be really big
        query = Postgrex.prepare!(conn, "", "SELECT pg_sleep(5)", timeout: 50_000)
        stream = Postgrex.stream(conn, query)
        result_to_iodata = fn(%Postgrex.Result{rows: rows}) ->
                                 format_query_result(rows) 
                           end
        Enum.into(stream, File.stream!("eg"), result_to_iodata)
    end,

    timeout: 30_000  #30 seconds
)

每当灵丹妙药文档定义如下函数时:

代码语言:javascript
复制
func_name(arg1, ...argN, opts \\ [] )

opts是关键字列表,例如:

代码语言:javascript
复制
[{:a, 1}, {:b, 2}]

但是,如果关键字列表是函数调用中的最后一个参数,则关键字列表可以如下所示:

代码语言:javascript
复制
func(arg1, arg2, a: 1, b: 2)

函数定义将接收以下三个参数

代码语言:javascript
复制
arg1, arg2, [{:a, 1}, {:b, 2}]

在任何情况下,默认的:timeout是:

代码语言:javascript
复制
:timeout - Transaction timeout (default: 15000);

错误上说:

连接不可用,请求在2950 was后从队列中删除。

因为2950 < 15000,它看起来不像是:timeout值是错误的来源。

错误消息继续:

没有连接..。可以使用:queue_target和:queue_interval配置请求在队列中等待的时间。有关更多信息,请参见DBConnection.start_link/2

解释了如何配置这些超时:

config/<env>.exs中(其中<env>是dev、test或prod): 配置:my_app,MyApp.Repo,适配器: Ecto.Adapters.Postgres,pool_size: 10,migration_timestamps: type::utc_datetime_usec,migration_lock: nil,queue_target: 5000 是我们最近由于生产中的错误数量增加而不得不做的事情。

也是

处理请求是通过队列完成的。启动DBConnection时,有两个相关选项来控制队列: :queue_target (毫秒),默认值为50 to (毫秒),默认为1000 to (毫秒) 我们的目标是等待最多的:queue_target连接。如果在:queue_interval期间签出的所有连接都比:queue_target多,那么我们将:queue_target加倍。如果签出连接比新目标花费的时间更长,那么我们就开始删除消息。 例如,默认情况下,我们的目标是50 is。如果所有的连接签出时间都超过50毫秒,我们将目标加倍到100毫秒,如果签出的时间超过新的限制,我们就开始删除消息。 这使我们能够更好地计划过载,因为我们可以在请求被发送到数据库之前拒绝它们,否则会增加数据库的负担,使重载更糟。

但是,如果您没有触及这些缺省值,那么我想知道为什么您在错误消息中看到的是2950ms,而不是更接近50 to或1000 to的东西。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56943306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档