在我的项目中,我正在运行一个返回大量数据的大量查询。由于此查询的大小,运行时有时超过1分钟。忽略这可能造成的其他问题,有没有办法取消当前运行的查询?
例如,用户启动查询并重定向到标准的“加载结果...”页面。如果他们然后决定他们不再需要结果,他们可以点击“取消”按钮,这将以某种方式终止正在运行的查询。
这可行,怎么办?
谢谢!
答案 0 :(得分:3)
答案 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