在Ruby on Rails中取消当前/活动查询

时间:2013-08-05 20:26:55

标签: ruby-on-rails ruby postgresql activerecord

在我的项目中,我正在运行一个返回大量数据的大量查询。由于此查询的大小,运行时有时超过1分钟。忽略这可能造成的其他问题,有没有办法取消当前运行的查询?

例如,用户启动查询并重定向到标准的“加载结果...”页面。如果他们然后决定他们不再需要结果,他们可以点击“取消”按钮,这将以某种方式终止正在运行的查询。

这可行,怎么办?

谢谢!

3 个答案:

答案 0 :(得分:3)

尝试使用pg_cancel_backend

来自文档:

  

取消后端的当前查询。您可以针对与调用该函数的用户具有完全相同角色的另一个后端执行此操作。在所有其他情况下,您必须是超级用户。

答案 1 :(得分:1)

我知道的唯一方法是重新启动数据库,尽管有时您可以发送取消信号,具体取决于数据库设置。您可以查看机架超时宝石吗?

真正的问题是您的查询不应该花那么长时间,我强烈建议不要这样处理问题。更好的方法是检查查询并尝试优化它。如果有任何查询应合法地花费1分钟完成,那么很少。获取数据转储到本地计算机上并在查询上运行EXPLAIN以查找瓶颈。我通过添加正确的索引得到了大的142s查询到<3s,所以如果你不能得到同样的效果我会感到惊讶。

答案 2 :(得分:1)

我最近做了类似的事情(在我们的应用程序中添加了“取消”按钮)。我一起攻击的plpgsql函数如下所示,它基本上是pg_cancel_backend()函数的包装器。

注意事项:

1)。您的应用程序必须创建一个唯一的ID(或UUID),并将其作为“p_uid”参数传递给该函数。

2)。我硬编码了应用程序用户(不会改变)。

3)。 Postgresql 9.0+(这是为9.2创建的,在任何早期版本中未经测试)

4)。该功能可以加强安全性。

CREATE OR REPLACE FUNCTION public.cancel_user_query(p_uid TEXT, OUT retval BOOLEAN) RETURNS boolean
AS $function$
DECLARE
BEGIN
    /*  The pg_sleep() call at the start is because if a user issues a query
        then promptly tries to kill it, it will likely not have shown up in the
        pg_stat_activity view yet (there is a delay before it appears).
        XXX: The GUC setting "track_activities" *MUST* be enabled for this to work.
    */

    retval := FALSE;
    IF ( current_setting('track_activities')::BOOLEAN IS NOT TRUE ) THEN
        RAISE WARNING '[PUBLIC.CANCEL_USER_QUERY] - "track_activities" *MUST* be enabled for this to work';
        RETURN;
    END IF;

    /* In a system under regular high load, this might need to be bumped higher than 2 seconds */
    PERFORM pg_sleep(2); 

    WITH q AS ( SELECT pid FROM pg_stat_activity WHERE LOWER(usename) = 'YOUR_APP_USER' AND application_name = p_uid AND state <> 'idle' )
    SELECT pg_cancel_backend(pid) AS retval
    INTO retval
    FROM q;

    if ( retval IS NOT TRUE ) then
        retval := FALSE;
    end if;

    RETURN;

EXCEPTION
    WHEN others THEN
        RAISE WARNING '[PUBLIC.CANCEL_USER_QUERY] - ERROR: %',sqlerrm;
        retval := FALSE;
        RETURN;
END;
$function$ LANGUAGE plpgsql SECURITY DEFINER;

单击“取消查询”按钮,应用程序执行该功能并检查返回的状态。 例如。 SELECT retval FROM public.cancel_user_query('asifdaqiwaviafasdf') retval