首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

PL/SQL 多進程通訊技術深度解析:DBMS_PIPE 與 DBMS_ALERT 實戰

     編輯:Oracle 資料庫基礎

為什麼 PL/SQL 需要多進程通訊

PL/SQL 設計初衷是強化 SQL 處理能力,缺乏原生多執行緒/多進程支援。若需並行處理提升吞吐量,必須透過 Oracle 提供的兩個套件實現會話間通訊:

  • DBMS_PIPE:命名管道,點對點、非同步、訊息佇列模型
  • DBMS_ALERT:事件通知/發布-訂閱模型,同步於交易提交

DBMS_PIPE 核心 API

函數/程序用途
PACK_MESSAGE(msg)將訊息封裝進本地緩衝區
SEND_MESSAGE(pipe_name, timeout)發送緩衝區至命名管道,回傳狀態碼 (0=成功)
RECEIVE_MESSAGE(pipe_name, timeout)從管道接收訊息至本地緩衝區
UNPACK_MESSAGE(var)解析緩衝區訊息至變數
CREATE_PIPE / REMOVE_PIPE建立/移除管道 (隱含於首次 SEND)
PURGE / RESET_BUFFER清除管道/本地緩衝區

DBMS_PIPE 範例:雙會話請求-回應

發送端 (Session A)

DECLARE
  v_pipe  VARCHAR2(30) := 'pipe_req';
  v_status INTEGER;
BEGIN
  DBMS_PIPE.PACK_MESSAGE('HELLO FROM SENDER');
  v_status := DBMS_PIPE.SEND_MESSAGE(v_pipe, 10);
  IF v_status != 0 THEN
    DBMS_OUTPUT.PUT_LINE('Send failed: ' || v_status);
  END IF;
END;
/

接收端 (Session B)

DECLARE
  v_pipe  VARCHAR2(30) := 'pipe_req';
  v_status INTEGER;
  v_msg   VARCHAR2(200);
BEGIN
  v_status := DBMS_PIPE.RECEIVE_MESSAGE(v_pipe, 30);
  IF v_status != 0 THEN
    DBMS_OUTPUT.PUT_LINE('Receive failed: ' || v_status);
  ELSE
    DBMS_PIPE.UNPACK_MESSAGE(v_msg);
    DBMS_OUTPUT.PUT_LINE('Got: ' || v_msg);
  END IF;
END;
/

DBMS_ALERT 核心 API

程序用途
REGISTER(alert_name)註冊監聽指定警示名稱
SIGNAL(alert_name, message)發送警示訊息 (於 COMMIT 時真正發送)
WAITONE(alert_name, msg OUT, status OUT, timeout)等待單一警示,逾時返回
WAITANY(alerts, name OUT, msg OUT, status OUT, timeout)等待任一已註冊警示
REMOVE/REMOVEALL移除註冊

DBMS_ALERT 範例:異步事件通知

發送端

DECLARE
  v_alert VARCHAR2(30) := 'order_event';
BEGIN
  DBMS_ALERT.SIGNAL(v_alert, 'New order #12345 inserted');
  COMMIT;  -- 必須 COMMIT 才會真正發送
END;
/

接收端

DECLARE
  v_alert  VARCHAR2(30) := 'order_event';
  v_msg    VARCHAR2(200);
  v_status INTEGER;
BEGIN
  DBMS_ALERT.REGISTER(v_alert);
  DBMS_ALERT.WAITONE(v_alert, v_msg, v_status, 60);  -- 等待 60 秒
  IF v_status = 0 THEN
    DBMS_OUTPUT.PUT_LINE('Alert received: ' || v_msg);
  ELSE
    DBMS_OUTPUT.PUT_LINE('Timeout or error: ' || v_status);
  END IF;
END;
/

兩者關鍵差異比較

特性DBMS_PIPEDBMS_ALERT
通訊模型點對點管道 (佇列)發布-訂閱 (廣播)
同步性非同步,立即發送/接收同步於 COMMIT,ROLLBACK 則不發送
訊息消費單一接收者消費後移除多訂閱者皆可收到 (僅複製)
資料型別支援 VARCHAR2, NUMBER, DATE, RAW 等 (透過 PACK/UNPACK)僅 VARCHAR2 文字訊息
緩衝區大小受限於 SGA pipe_size (預設 8K)較小,適合簡短通知
典型用途背景作業協調、外部程式互動、複雜資料傳遞事件驅動觸發、快取失效通知、跨會話訊號

進階應用模式

  1. 工作隊列:主進程將任務封裝送入管道,多個 Worker 進程並行 RECEIVE/PROCESS/回覆結果管道。
  2. 快取失效廣播:資料變更時 SIGNAL 'cache_inval_',應用層會話 REGISTER/WAITONE 即時刷新本地快取。
  3. 外部程式整合:Pro*C/Oracle Call Interface (OCI) 進程作為管道端點,實現資料庫與 OS 層雙向通訊 (如前文 DBMS_PIPE 範例)。
  4. 效能與限制提醒

    • 管道訊息駐留於 SGA,大量/大訊息可能衝擊共用池,需監控 V$DB_PIPES。
    • ALERT 訊號在 COMMIT 前不會發送,長交易會延遲通知;若需即時性請用 PIPE。
    • 兩者皆非持久化,資料庫重啟後管道/警示消失,重要狀態須自行持久化至表格。
    • 12c+ 可考慮 DBMS_AQ (Advanced Queuing) 取代,提供持久化、優先級、延遲投遞等企業級佇列功能。
    1. 上一篇文章:
    2. 下一篇文章:
    Copyright © 程式碼之家 All Rights Reserved