pg_connection_busy() 返回 true 並不一定意味著有結果正在等待 pg_get_result();在導致任何種類 Postgres 錯誤的查詢之後的一段時間內,它也會保持 true。(參見 http://bugs.php.net/bug.php?id=36469)
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
pg_connection_busy — 取得連線是否忙碌
pg_connection_busy() 判斷連線是否忙碌。如果忙碌,表示先前的查詢仍在執行中。如果在連線上使用 pg_get_result(),它將會被阻塞。
版本 | 說明 |
---|---|
8.1.0 | connection 參數現在需要一個 PgSql\Connection 實例;先前需要的是 資源。 |
範例 #1 pg_connection_busy() 範例
<?php
$dbconn = pg_connect("dbname=publisher") or die("無法連線");
$bs = pg_connection_busy($dbconn);
if ($bs) {
echo '連線忙碌';
} else {
echo '連線閒置';
}
?>
pg_connection_busy() 返回 true 並不一定意味著有結果正在等待 pg_get_result();在導致任何種類 Postgres 錯誤的查詢之後的一段時間內,它也會保持 true。(參見 http://bugs.php.net/bug.php?id=36469)
這裡似乎沒有任何關於如何使用此函數的說明文件,而且我認為大多數嘗試使用此函數的人在等待時如果沒有其他事情可做,會預設使用忙碌迴圈(在這種情況下,pg_get_result 會更好,因為它會一直阻塞直到結果準備好),或者如果嘗試在特定時間後取消查詢,則使用睡眠迴圈。
libPq 的 C 文件建議使用 PQisBusy(pg_connection_busy 的 C 等效項)通過等待套接字來代替,這允許您在狀態在特定時間段後沒有改變時設定逾時,但如果狀態改變則立即反應。如果您想在逾時後取消,您可以執行以下操作
<?php
class SomeKindOfTimeoutException extends Exception { }
class SomeKindOfSQLErrorException extends Exception { }
function query_with_timeout($conn, $query, $timeout_seconds) {
assert(pg_get_result($conn) === false); // 確保沒有正在執行的查詢
$socket = [pg_socket($conn)];
$null = [];
$dispatch_ok = pg_send_query($conn, $query);
$still_running = pg_connection_busy($conn);
while($still_running) {
// https://postgresql.dev.org.tw/docs/current/libpq-async.html
// 「使用這些函式的典型應用程式將具有一個主迴圈,該迴圈使用 select() 或 poll() 來等待它必須響應的所有條件。」
// 「其中一個條件將是來自伺服器的可用輸入,就 select() 而言,這意味著由 PQsocket 標識的檔案描述符上的可讀數據。」
// PQisBusy 對應到 pg_connection_busy
stream_select($socket, $null, $null, $timeout_seconds); // 將在該 socket 上等待,直到發生該情況或達到逾時
$still_running = pg_connection_busy($conn); // 逾時時為 False,完成時為 True
// 您可以像這樣繼續輪詢,這只是在第一個迴圈中立即中斷並拋出異常
if ($still_running) {
$cancel_ok = pg_cancel_query($conn);
throw new SomeKindOfTimeoutException("TIMEOUT");
}
}
$res = pg_get_result($conn);
try {
$error_msg = pg_result_error($res);
if ($error_msg) throw new SomeKindOfSQLErrorException($error_msg);
return pg_fetch_all($res);
} finally {
pg_free_result($res);
}
}
$conn_string = "host=localhost port=5433 dbname=postgres";
$db = pg_connect($conn_string);
query_with_timeout($db, "SELECT pg_sleep(10)", 3); // 將拋出異常
?>