2013-10-12 20 views
7

我在閱讀libpq參考。它具有同步和異步方法。我發現了一些奇怪的東西。爲什麼`libpq`使用輪詢而不是通知來獲取數據?

當我看到PQsendQuery函數時,它似乎發送一個查詢並立即返回。我希望有一個回調函數來獲得通知,但是沒有這樣的事情,並且手冊說輪詢的數據可用性。

我不明白爲什麼異步方法是以輪詢方式編寫的。無論如何,因爲libp是官方的客戶端實現,我相信這個設計應該有一個很好的理由。那是什麼?或者我錯過了在其他地方提到的正確回調的東西?

+3

只是稍後註釋:'libpq'具有'PQsocket'函數,該函數返回*套接字的文件描述符*。要通知數據可用性,請使用系統API監視此套接字。 ('kqueue','libdispatch'等) – Eonil

+2

現在我終於明白了這個設計。這只是阻塞與非阻塞*風格*的區別,API的形式對性能來說並不重要。 – Eonil

回答

6

在單線程程序的執行模型中,執行流程不能被異步查詢返回的數據或更一般的網絡套接字中斷。只有信號(SIGTERM和朋友)可能會中斷流量,但信號不能掛接到數據進入。

這就是爲什麼有一個回調來獲取傳入數據的通知是不可能的。如果你的代碼沒有調用它,那麼libpq中用於發出回調所需的代碼永遠不會運行。如果你不得不稱呼它,那就會挫敗回調的全部。

有類似Qt這樣的庫提供回調,但是它們是從頭開始架構的,具有充當事件處理器的主循環。用戶代碼在回調中進行組織,並且可以對傳入數據進行基於事件的處理。但在這種情況下,該庫將獲取執行流程的所有權,這意味着它的主循環會輪詢數據源。這只是將職責轉移到libpq之外的另一段代碼。

+0

看來'libpq'是爲單線程程序設計的。性能好嗎? – Eonil

+3

@Eonil:任何網絡客戶端都必須在套接字上等待。 'libpq'只是向庫用戶公開這一點,使得可以將'libpq'與現有的事件庫(比如'libevent'或Linux'epoll')一起使用。這使得'libpq'比使用阻塞客戶端(例如http://www.kegel.com/c10k.html#threaded)更具有可伸縮性,而不會浪費等待和等待數據庫的線程。所以是的,這對性能非常有利。 – ArtemGr

-1

此頁面描述如何獲得異步結果獲取的通知。

http://www.postgresql.org/docs/9.3/static/libpq-events.html#LIBPQ-EVENTS-PROC

PGEVT_RESULTCREATE

結果創建事件是響應燒製以任何查詢執行 功能,其產生的結果,其中包括PQgetResult時。此事件 只有在結果成功創建後纔會被觸發。

typedef struct { PGconn * conn; PGresult * result; } PGEventResultCreate;當收到PGEVT_RESULTCREATE事件時,evtInfo指針應該轉換爲 PGEventResultCreate *。 conn是用於生成 結果的連接。這是初始化 需要與結果關聯的任何實例數據的理想位置。如果事件過程失敗, 結果將被清除並且失敗將被傳播。 事件過程不得嘗試PQclear自己的結果對象。 當返回失敗代碼時,必須執行所有清理,因爲不會發送 PGEVT_RESULTDESTROY事件。

+2

這並不會改變'PQsendQuery'之後的輪詢需求。如果你不這樣做,這個事件將永遠不會被解僱。 –

相關問題