支持的版本:当前 (17) / 16 / 15 / 14 / 13
开发版本:devel
不支持的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0

32.7. 取消正在进行的查询 #

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 检索错误消息。

但是,成功发送取消并不保证该请求会产生任何影响。如果取消有效,则正在取消的命令将提前终止并返回错误结果。如果取消失败(例如,因为服务器已经完成处理命令),则根本不会有任何可见的结果。

PQcancelStart
PQcancelPoll #

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

int PQcancelStart(PGcancelConn *cancelConn);

PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn);

该请求通过给定的 PGcancelConn 发出,该 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,表示已成功发送取消请求。

但是,成功发送取消并不保证该请求会产生任何影响。如果取消有效,则正在取消的命令将提前终止并返回错误结果。如果取消失败(例如,因为服务器已经完成处理命令),则根本不会有任何可见的结果。

在连接期间的任何时候,都可以通过调用 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 的条目。

但是,成功发送取消并不保证该请求会产生任何影响。如果取消有效,则正在取消的命令将提前终止并返回错误结果。如果取消失败(例如,因为服务器已经完成处理命令),则根本不会有任何可见的结果。

PQcancelSocket #

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

int PQcancelSocket(const PGcancelConn *cancelConn);

有效的描述符将大于或等于 0;结果为 -1 表示当前没有打开的服务器连接。在 PGcancelConn 上调用此部分中的任何函数(除了 PQcancelErrorMessagePQcancelSocket 本身)可能会导致这种情况发生变化。

PQcancelErrorMessage #

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

char *PQcancelErrorMessage(const PGcancelConn *cancelconn);

几乎所有接受 PGcancelConnlibpq 函数都会在失败时为 PQcancelErrorMessage 设置消息。请注意,按照 libpq 的约定,非空的 PQcancelErrorMessage 结果可以包含多行,并且会包含一个尾随换行符。调用者不应直接释放结果。当相关的 PGcancelConn 句柄传递给 PQcancelFinish 时,它将被释放。不应期望结果字符串在 PGcancelConn 结构上的操作中保持不变。

PQcancelFinish #

关闭取消连接(如果尚未完成发送取消请求)。还会释放 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 的字符数组(建议的大小为 256 字节)。

PQrequestCancel #

PQrequestCancelPQcancelBlocking 的已弃用且不安全的变体。

int PQrequestCancel(PGconn *conn);

PQrequestCancel 的存在仅仅是因为向后兼容性的原因。应该使用 PQcancelBlocking。 使用 PQrequestCancel 没有任何好处,而不用 PQcancelBlocking

请求服务器放弃处理当前命令。它直接在 PGconn 对象上操作,并且在发生故障时将错误消息存储在 PGconn 对象中(可以从中通过 PQerrorMessage 检索)。尽管功能相同,但这种方法在多线程程序或信号处理程序中是不安全的,因为覆盖 PGconn 的错误消息可能会搞乱当前在连接上进行的操作。

提交更正

如果您发现文档中的任何内容不正确、与您使用特定功能的经验不符或需要进一步澄清,请使用此表单报告文档问题。