当用户在飞行中中止他的请求时,我有时会取消任何支持他当时尝试的任何只读操作的只读语句 - 我谨慎地遵循这种模式 - 仅为在高流量期间发生的昂贵查询保留因此有可能引起争用。
在 PG 中,我取消查询,如下所示:
SELECT pg_cancel_backend(pid)
;
当我这样做时,PG 会遵守但会记录以下内容:Error: canceling statement due to user request
。
我明白为什么它的兄弟pg_terminate_backend
会将自己归类为错误;这是强制终止进程的最后一搏,具有潜在危险的尝试。
但我不明白为什么通常的查询取消会被同样对待。毕竟我已经请求取消,那么为什么会以如此高的严重级别记录它呢?
根据 SQL 标准,数据库引擎必须通过 SQLSTATE 变量传达每个已完成命令的条件,并且 SQLSTATE 的值精确指示命令如何完成。该标准将 SQLSTATE 值分为几类;客户可以并且将会以不同方式对待来自每个组的代码。
所涉及的特定条件“query_cancelled”被分配代码 57014,属于“错误”类。相应地,当
psql
看到 SQLSTATE 57014 响应其命令时,它会将其视为错误,并打印适当的消息。您之所以会出现此行为,是因为从启动 SELECT 查询的客户端程序的角度来看,取消该查询是一个错误。
默认情况下,根本不清楚启动 SELECT(或可能是任何命令)的用户是否是运行该
pg_cancel_backend
调用的用户。它可能是不同的用户(具有相同的非特权帐户)或超级用户。假设我作为 DBA 在您不知情或不同意的情况下取消了您的查询;您肯定希望收到一条与此相关的令人心酸的错误消息,而不仅仅是窗口角落里的一个小通知,显示结果为 0,或者类似的东西。从概念上讲,如果不报告错误,结果会怎样?然后,客户端会期望一些结果集 - 一些记录,或一个空集。两者都会是错误的返回值——它们会表明那里有一些结果,但事实并非如此。当然,如果它是一个实际的客户端程序(而不是某些 SQL 工具中的用户会话),您肯定会希望像往常一样启动任何异常处理,以保持一致。