Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

32.7 正在执行的取消查询 #

32.7.1 发送取消请求的函数
32.7.2 发送取消请求的旧函数

32.7.1.用于发送取消请求的函数 #

PQcancelCreate #

准备一个连接,可通过该连接发送取消请求。

PGcancelConn *PQcancelCreate(PGconn *conn);

PQcancelCreate 创建一个 PGcancelConn 对象,但不会立即开始通过此连接发送取消请求。可以通过使用 PQcancelBlocking 以阻塞方式通过此连接发送取消请求,或使用 PQcancelStart 以非阻塞方式发送。返回值可以传递给 PQcancelStatus 以检查是否成功创建了 PGcancelConn 对象。PGcancelConn 对象是不透明的结构,不供应用程序直接访问。此 PGcancelConn 对象可用于以线程安全的方式取消正在原始连接上运行的查询。

在为取消请求设置连接时,将重复使用原始客户端的许多连接参数。重要的是,如果原始连接需要加密连接和/或验证目标主机(使用 sslmodegssencmode),那么取消请求的连接也将具有相同要求。但是,会在取消请求中忽略任何仅仅在身份验证期间或客户端身份验证后才会使用的连接选项,因为取消请求不需要身份验证,且连接会在提交取消请求之后立即关闭。

请注意,当 PQcancelCreate 返回非空指针时,在使用完此指针后,必须调用 PQcancelFinish 以释放该结构以及任何关联的内存块。即使取消请求失败或放弃,也必须这样做。

PQcancelBlocking #

以阻塞方式请求服务器放弃处理当前命令。

int PQcancelBlocking(PGcancelConn *cancelConn);

该请求通过给定的 PGcancelConn 发起,该 PGcancelConn 需要使用 PQcancelCreate 创建。如果取消请求成功分派,则 PQcancelBlocking 的返回值为 1;如果不成功,则返回 0。如果请求不成功,可以使用 PQcancelErrorMessage 检索错误消息。

但是,取消 dispatch 成功并不保证该请求会产生任何效果。如果取消有效,待取消的命令会提早终止并返回错误结果。如果取消失败(例如,因为服务器已完成处理命令),那么根本不会出现可见结果。

PQcancelStart
PQcancelPoll #

请求服务器以非阻塞方式停止处理当前命令。

int PQcancelStart(PGcancelConn *cancelConn);

PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn);

可以通过 PGcancelConn 发起请求,需要通过 PQcancelCreate 创建该连接。如果可以发起取消请求,PQcancelStart 的返回值将为 1;否则为 0。如果此次请求不成功,可以通过 PQcancelErrorMessage 检索错误消息。

如果 PQcancelStart 成功,接下来的步骤是对 libpq 进行轮询以便继续取消连接序列。使用 PQcancelSocket 获取数据库连接底层套接字的描述符(注意:不要假设 PQcancelPoll 调用过程中套接字保持不变)。循环如下:如果 PQcancelPoll(cancelConn) 上一次返回 PGRES_POLLING_READING,则等待套接字准备读取( select()poll() 或类似系统函数指示)。然后再次调用 PQcancelPoll(cancelConn)。相反,如果 PQcancelPoll(cancelConn) 上一次返回 PGRES_POLLING_WRITING,则等待套接字准备写入,然后再次调用 PQcancelPoll(cancelConn)。在第一次迭代中,即如果尚未调用 PQcancelPoll(cancelConn),则像上一次返回 PGRES_POLLING_WRITING 一样。继续执行此循环,直到 PQcancelPoll(cancelConn) 返回 PGRES_POLLING_FAILED(指示连接过程已失败)或返回 PGRES_POLLING_OK(指示取消请求已成功 dispatch)。

但是,取消 dispatch 成功并不保证该请求会产生任何效果。如果取消有效,待取消的命令会提早终止并返回错误结果。如果取消失败(例如,因为服务器已完成处理命令),那么根本不会出现可见结果。

在连接过程中,可以使用 PQcancelStatus 来随时检查连接状态。如果该调用返回 CONNECTION_BAD,则取消过程失败;如果该调用返回 CONNECTION_OK,则已成功发送取消请求。上述状态都可从 PQcancelPoll 的返回值中检测到。此外,在异步连接过程中(以及仅在该过程中),也可能会出现其他状态。这些状态表示连接过程的当前阶段,可供用户提供反馈。这些状态是:

CONNECTION_ALLOCATED #

等待调用 PQcancelStartPQcancelBlocking 实际打开套接字。这是在调用 PQcancelCreatePQcancelReset 之后的连接状态。此时尚未连接到服务器。如需实际开始发送取消请求,请使用 PQcancelStartPQcancelBlocking

CONNECTION_STARTED #

等待建立连接。

CONNECTION_MADE #

连接正常;等待发送。

CONNECTION_AWAITING_RESPONSE #

等待来自服务器的响应。

CONNECTION_SSL_STARTUP #

正在协商 SSL 加密。

CONNECTION_GSS_STARTUP #

正在协商 GSS 加密。

请注意,尽管这些常量会保留(以维持兼容性),但是应用程序不应依赖于这些常量以特定顺序或以任何方式出现,或者依赖于该状态始终为其中一个记录值。应用程序可能会执行以下操作:

switch(PQcancelStatus(conn))
{
        case CONNECTION_STARTED:
            feedback = "Connecting...";
            break;

        case CONNECTION_MADE:
            feedback = "Connected to server...";
            break;
.
.
.
        default:
            feedback = "Connecting...";
}

使用 PQcancelPoll 时,将忽略 connect_timeout 连接参数;由应用程序决定是否经过了一段时间。否则,PQcancelStart 后跟一个 PQcancelPoll 循环等同于 PQcancelBlocking

PQcancelStatus #

返回取消连接的状态。

ConnStatusType PQcancelStatus(const PGcancelConn *cancelConn);

状态可以是多个值中的一种。但是,只有三个值在异步取消过程中不可见:CONNECTION_ALLOCATEDCONNECTION_OKCONNECTION_BAD。使用 PQcancelCreate 成功创建的 PGcancelConn 的初始状态是 CONNECTION_ALLOCATED。已成功发送的取消请求状态为 CONNECTION_OK。状态 CONNECTION_BAD 表示取消尝试失败。在调用 PQcancelFinishPQcancelReset 之前,OK 状态将保持不变。

请参阅 PQcancelStart 条目以了解可能返回的其他状态代码。

但是,取消 dispatch 成功并不保证该请求会产生任何效果。如果取消有效,待取消的命令会提早终止并返回错误结果。如果取消失败(例如,因为服务器已完成处理命令),那么根本不会出现可见结果。

PQcancelSocket #

获取到服务器取消连接套接字的文件描述符编号。

int PQcancelSocket(const PGcancelConn *cancelConn);

有效的文件描述符将大于或等于 0;结果为 -1 表示当前尚未打开任何服务器连接。调用此部分中 PGcancelConn 的任何函数(PQcancelErrorMessagePQcancelSocket 除外)可能会造成此状态的变化。

PQcancelErrorMessage #

返回取消连接操作最近生成错误消息。

char *PQcancelErrorMessage(const PGcancelConn *cancelconn);

如果失败,几乎所有 libpq 函数(将 PGcancelConn 作为参数的函数)都将为 PQcancelErrorMessage 设置一条消息。请注意,根据 libpq 约定,非空 PQcancelErrorMessage 结果可以包含多行并包括一个尾换行符。调用者不应直接释放此结果。当将关联的 PGcancelConn 句柄传递给 PQcancelFinish 时,它将被释放。切勿期望结果字符串在对 PGcancelConn 结构执行操作后保持不变。

PQcancelFinish #

如果尚未完成发送取消请求,关闭取消连接(Cancels the cancel connection)。还会释放PGcancelConn对象所使用的内存。

void PQcancelFinish(PGcancelConn *cancelConn);

请注意,即使取消尝试失败(由PQcancelStatus指示),应用程序也应调用PQcancelFinish,以释放PGcancelConn对象所使用的内存。在调用PQcancelFinish之后,不得再使用PGcancelConn指针。

PQcancelReset #

重置PGcancelConn,以便可将其重新用于新的取消连接。

void PQcancelReset(PGcancelConn *cancelConn);

如果PGcancelConn当前用于发送取消请求,则关闭此连接。然后,将准备PGcancelConn对象,以便可将其用于发送新的取消请求。

可使用此功能为PGconn创建一个PGcancelConn,并在原始PGconn的整个使用寿命期间多次重复使用该连接。

32.7.2. 发送取消请求的过时函数#

这些函数表示发送取消请求的旧方法。尽管它们仍然可用,但由于未以加密方式发送取消请求(即使原始连接指定sslmodegssencmode以要求进行加密),因此不建议使用。因此,强烈建议不要在新代码中使用这些旧方法,并且建议更改现有代码以改用新函数。

PQgetCancel #

创建一个包含使用PQcancel取消命令所需信息的数据结构。

PGcancel *PQgetCancel(PGconn *conn);

PQgetCancel会根据PGconn连接对象创建一个PGcancel对象。如果给定的connNULL或无效连接,它会返回NULLPGcancel对象是不透明结构,应用程序不应直接访问它;它只能传递给PQcancelPQfreeCancel

PQfreeCancel #

释放 PQgetCancel 创建的数据结构。

void PQfreeCancel(PGcancel *cancel);

PQfreeCancel 释放之前由 PQgetCancel 创建的数据对象。

PQcancel #

PQcancelPQcancelBlocking 的已过时且不安全的变体,但可在信号处理程序之中安全使用。

int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);

仅因向后兼容性的原因而存在 PQcancel。应改用 PQcancelBlockingPQcancel 拥有的唯一优点是,如果信号处理程序中的errbuf是局部变量,那么可以从信号处理程序中安全调用它。但通常认为,这不足以弥补此函数存在的安全问题。

对于 PQcancel 来说,PGcancel 对象是只读的,因此也可以从不同于操作PGconn对象的线程中调用它。

如果已成功发送取消请求,PQcancel 的返回值为 1;否则为 0。如果不是,errbuf 中会填充解释性错误消息。errbuf 必须是大小为errbufsize的 char 数组(建议大小为 256 个字节)。

PQrequestCancel #

PQrequestCancelPQcancelBlocking 的已过时且不安全的变体。

int PQrequestCancel(PGconn *conn);

仅因向后兼容性的原因而存在 PQrequestCancel。应改用 PQcancelBlocking。相对于 PQcancelBlocking,使用 PQrequestCancel 没有任何好处。

请求服务器放弃处理当前命令。它直接在 PGconn 对象上运行,并且在失败的情况下,会将错误消息存储在 PGconn 对象中(可通过 PQerrorMessage 检索)。虽然功能相同,但此方法在多线程程序或信号处理程序中不安全,因为覆盖 PGconn 的错误消息可能会破坏当前在连接上进行的操作。