| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 27. libpq - C 庫 | Fast Forward | Next |
PostgreSQL 通過LISTEN和NOTIFY命令提供對異步通知的支持。 一個服務器用LISTEN命令注冊一個它感興趣的通知條件 (也可以用UNLISTEN命令停止監聽)。 所有正在監聽某一通知條件的會話在該條件名的 NOTIFY(通知)被任何會話執行後都將被異步地通知。 通知發出者不會傳遞附加的信息到監聽者。因此,很典型地是, 任何實際的需要被傳遞的數據都是通過一個數據庫表傳遞的。 通常,條件名與相關聯的表同名,但是並不是一定要與某個表相關才行。
libpq 應用把LISTEN和 UNLISTEN 命令作為通常的 SQL 命令提交。 隨後通過調用PQnotifies()可以偵測到 NOTIFY 消息的到達。
函數PQnotifies 從一個來自服務器的未處理的通知信息列表中返回下一條通知。 如果沒有未處理的信息則返回 NULL 指針。 一旦PQnotifies返回一條通知, 該通知會被認為已處理並且將被從通知列表中刪除。
PGnotify* PQnotifies(PGconn *conn);
typedef struct pgNotify {
char *relname; /* 通知名字*/
int be_pid; /* 服務器進程 id*/
char *extra; /* 通知參數 */
} PGnotify;在處理完 PQnotifies 返回的PGnotify對象後, 別忘了用PQfreemem() 把它釋放,以避免內存洩漏。 釋放 PGnotify 指針就足夠了;relname 和 extra 字段並未代表獨立分配的內存。(目前,extra 字段沒有使用, 並且將總是指向一個空字串。)
注意: 在 PostgreSQL 6.4 和更高的版本裡, be_pid 是正在通知的服務器的 PID, 而在早些的版本裡它總是你自己的服務器的PID。
Example 27-2 給出了一個使用異步通知的例子。
PQnotifies() 實際上並不讀取服務器數據; 它只是返回被前面的另一個libpq函數吸收的信息。 在以前的 libpq 的版本裡, 週期性的收到NOTIFY信息的唯一方法是持續的提交命令, 即使是空查詢也可以,並且在每次 PQexec()後檢查 PQnotifies() 。現在這個方法也能還工作, 不過我們認為它太浪費處理器時間而廢棄了它。
在你沒有可用的命令提交時檢查NOTIFY消息的更好的方法是調用 PQconsumeInput(),然後檢查 PQnotifies()。你可以使用 select() 來等待服務器數據的到達, 這樣在沒有數據可處理時可以不浪費 CPU 時間。 (參閱PQsocket() 獲取用于 select()的文件描述符。) 注意這種方法不管你使用 PQsendQuery/PQgetResult 還是簡單的 PQexec來執行命令都能工作。不過,你應該記住在每次 PQgetResult 或 PQexec後檢查 PQnotifies() ,看看在處理命令的過程中是否有通知到達。