PostgreSQL:LISTEN | NOTIFY

Ryan_Bai發表於2020-12-19

pg 中的 Listen/Notify 是用來提供客戶端之間透過服務段進行訊息通訊的機制。

  • listen:監聽訊息通道

  • unlisten:取消先前的監聽

  • notify:傳送訊息到訊息通道中

  • pg_notify():與 notify 命令的功能相同,也可以傳送訊息到訊息同道中。

  • pg_listening_channels():呼叫此函式可以查詢當前 session 已註冊了哪些訊息監聽。

LISTEN

LISTEN channel (channel值任意)
  • 用來註冊一個訊息通道。

  • 如果在事務中執行 listen,那麼事務必須成功 commit,listen才生效。

  • session 退出後 listen 自動釋放。

NOTIFY

NOTIFY channel [, payload] (payload預設要求小於8000位元組, 且必須是常量)
  
-- OR
pg_notify(channel, payload)
  • 用來往訊息通道傳送非同步訊息。

  • 如果在事務中執行 notify,那麼必須等事務成功 commit 之後這個訊息才會塞進訊息佇列。

  • 訊息在事務和事務之間的間隙傳遞。因此如果有一個 listen 的 session 中跑了一個很長的事務,那麼要等這個事務結束才能接收到這個過程中發出的 notify。

  • 一個訊息如果在發出 notify 之前有監聽者,必須等這些監聽者都接收到了這個訊息才從訊息佇列中去除。

UNLISTEN

UNLISTEN { channel | *)}

註冊訊息監聽後,如果不想再收到相應的訊息,可以使用 UNLISTEN 取消監聽。UNLISTEN * 可以取消所有監聽的註冊,在會話結束是也會自動執行這個命令。

示例

通用場景

多個 session 可以同時監聽同一個訊息通道。當傳送端傳送一個訊息時,所有監聽者都可能收到此訊息。

-- session 1
postgresql > listen test
 
-- session 2
postgresql > listen test
 
-- session 3
postgresql > notify test, 'hello world';
 
-- session 1
postgresql > select 1;
 
-- session 2
postgresql > select 1;

回滾場景

如果在事務中呼叫 notify 傳送訊息,實際訊息要在事務提交時才會被髮送,如果事務回滾了,訊息將不會傳送

-- session 1
postgresql > listen test
 
-- session 2
postgresql > begin;
postgresql > notify test, 'hello world';
 
-- session 1
postgresql > select 1;
 
-- session 2
postgresql > begin;
postgresql > notify test, 'hello world';
postgresql > end;
 
-- session 1
postgresql > select 1;

相同訊息

如果在一個事務中傳送兩條訊息的通道名稱相同,訊息字串也完全相同,則實際上只有一條訊息傳送出去

-- session 1
postgresql > listen test
 
-- session 2
postgresql > notify test, 'hello world1';
postgresql > notify test, 'hello world1';
postgresql > notify test, 'hello world2';
 
-- session 1
postgresql > select 1;

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31490526/viewspace-2743682/,如需轉載,請註明出處,否則將追究法律責任。

相關文章