2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 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 訊號。OK 狀態將一直保持,直到呼叫 PQcancelFinishPQcancelReset

有關其他可能返回的狀態程式碼,請參閱 PQcancelStart 的條目。

成功分派取消請求並不保證該請求一定有效。如果取消有效,正在取消的命令將提前終止並返回錯誤結果。如果取消失敗(例如,因為伺服器已完成處理命令),則不會有任何可見的結果。

PQcancelSocket #

獲取到伺服器的取消連線套接字的檔案描述符編號。

int PQcancelSocket(const PGcancelConn *cancelConn);

有效的描述符將大於或等於 0;結果 -1 表示當前沒有開啟伺服器連線。這可能會因為在本節的任何函式(除了 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 的存在僅出於向後相容性原因。應使用 PQcancelBlocking 代替。 PQcancel 唯一的優點是如果 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 的錯誤訊息可能會干擾正在進行的連線操作。

提交更正

如果您在文件中發現任何不正確、與您對特定功能的使用經驗不符或需要進一步澄清的內容,請使用 此表格 報告文件問題。