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

DB2 Universal Database 中實現訊息管道機制

     編輯:DB2 教學

前言

在先前的文章〈在 DB2 通用資料庫中實現會話間警告〉中,我們介紹了如何利用兩個資料庫會話之間的警示(alert)建立通訊管道。本文將提供另一種會話間通訊的實作方式——訊息管道。警示與管道皆可在非同步與同步兩種模式下運作,但兩者有本質差異:管道能將單一訊息的分組從一個會話傳輸至另一個會話,而警示僅能觸發另一會話採取行動。透過管道,您可以實際地將由不同資料類型組成的訊息封包從一個會話傳遞至另一個會話。此實作類似 Oracle 的 DBMS_PIPE 套件,但在細節上有所不同,若您計畫將應用程式從 Oracle 移植至 DB2 Universal Database,此機制將相當實用。

管道套件的組成

此管道實作包含以下資料庫物件:

  • 3 個目錄表
  • 2 個使用者定義函數
  • 28 個 SQL 預存程序

運作原理

管道通訊需要兩個參與會話:會話 A 負責準備並發送訊息封包至資料庫目錄;會話 B 負責接收、讀取封包並關閉管道。

會話 A 的操作流程

  1. 建立命名管道:可指定大小限制與類型(public 或 private)。
  2. 封裝訊息:將訊息打包至命名管道或暫存管道。管道必須處於開啟狀態且存在於目前會話。若命名管道不存在,系統會自動建立一個無大小限制的 public 暫存管道並封裝訊息。若管道類型為 private,所有訊息將被加密。
  3. 持續封裝:若訊息封包包含多條訊息,繼續打包。
  4. 發送封包:若為暫存管道,需提供一個名稱。

會話 B 的操作流程

  1. 接收並開啟管道。
  2. 檢查資料類型並讀取:採 FIFO(先進先出)順序檢查與讀取訊息。確認資料類型後,將資訊通知呼叫應用程式。
  3. 解包並儲存:呼叫端應用程式將訊息解包並存入對應型別的變數。若為 private 管道,需先解密再讀取。若管道無其他訊息則關閉,否則重複步驟 2 與 3。

管道管理功能

除核心通訊功能外,尚提供三項管理功能:

  • 建立者可刪除關閉狀態的管道。
  • 資料庫管理員可刪除任何使用者建立的關閉狀態管道。
  • 建立者可清除並重複使用關閉狀態的管道。
圖 1. 建立、封裝與發送管道
圖 1. 建立、封裝與發送管道
圖 2. 接收、檢查管道並解包
圖 2. 接收、檢查管道並解包

設計檢視

為支援管道功能,實作了三類資料庫物件:

目錄表

  • DBMS_PIPE.PIPES:儲存管道定義
  • DBMS_PIPE.PIPEMEMBERS:以純文字格式儲存訊息
  • DBMS_PIPE.PIPEMEMBERS_ENCRYPT:以加密字串格式儲存訊息

使用者定義函數

  • DBMS_PIPE.DELAY:提供以秒為單位的延遲
  • DBMS_PIPE.SESSION_ID:從資料庫管理器擷取會話 ID

註:這兩個函數的原始碼可參考前文〈在 DB2 通用資料庫中實現會話間警告〉,此處使用已編譯版本。

SQL 預存程序

  • DBMS_PIPE.CREATE_PIPE:建立命名管道(3 種多載)
  • DBMS_PIPE.PACK_MESSAGES_xxxx:將訊息封裝至管道(9 種,對應不同資料類型)
  • DBMS_PIPE.SEND_MESSAGE:發送管道以供處理(2 種多載)
  • DBMS_PIPE.RECEIVE_MESSAGE:擷取管道以供讀取
  • DBMS_PIPE.NEXT_ITEM_TYPE:檢查首個已封裝但未檢查訊息的資料類型
  • DBMS_PIPE.UNPACK_MESSAGES_x:讀取訊息並關閉管道(9 種,對應不同資料類型)
  • DBMS_PIPE.PURGE:清除管道訊息並將狀態重設為 PACKING
  • DBMS_PIPE.REMOVE_PIPE:由建立者從系統移除管道
  • DBMS_PIPE.DELETE_PIPE:由管理員刪除管道

目錄表結構

DBMS_PIPE.PIPES 包含 8 個欄位:

欄位說明
PID管道 ID
PNAME管道名稱
PTYPE管道類型(Y - Private,N - Public)
POWNER管道建立者名稱
PSTATUS管道狀態(P - Packing, S - Sent, O - Open, R - Reading, C - Closed)
PNDATA管道中訊息編號
PSIZE管道大小限制(位元組)
PTEMPNAME管道暫存名稱(設為會話 ID)

DBMS_PIPE.PIPEMEMBERS 包含 6 個欄位:

欄位說明
SLNO序號
PID管道 ID(外鍵連結至 PIPES.PID)
MID管道中的成員/訊息 ID
MTID成員/訊息資料類型 ID
NDIF成員/訊息狀態(N:未檢查,C:已檢查,R:已讀取)
DATA成員/訊息資料(純字串格式)

DBMS_PIPE.PIPEMEMBERS_ENCRYPT 結構相同,但 DATA 欄位儲存加密字串。

實用程式

下載包含四個實用程式,需以 SYSADM 身分從 COMMAND WINDOW 執行(勿從 MS-DOS 視窗):

  • pipesetup.bat:編譯所有預存程序並註冊上述物件。
  • getroutines.bat:將所有 SQL 預存程序以二進位格式匯出至 SAR 檔案。
  • putroutines.bat:從 SAR 檔案匯入所有 SQL 預存程序,不重新編譯。
  • cleanup.bat:從資料庫系統清除整個管道實作。

注意:編譯 SQL 預存程序需伺服器具備 VC++ v5.0/v6.0 或 CYGWIN GCC 及 Java 編譯器。無 VC++ 時可使用 CYGWIN GCC。

差異、優點與限制

  • 管道功能透過三個目錄表實作,不使用共享記憶體,因此更穩定、不受可用記憶體大小影響,且更可靠(無直接存取共享記憶體路徑,所有資料操作由資料庫伺服器完成)。
  • 單一訊息大小上限 32,631 位元組,但訊息封包(管道大小)無大小限制;Oracle 管道上限僅 4 KB。
  • 封裝與解包需不同預存程序,因預存程序不支援多載。
  • LONG 或 LOB 型別訊息無法直接封裝,但有替代方案可達成。
  • 可在多重分區環境中實作,所有表應選擇 PID 作為分區鍵,確保同一管道資料儲存於同一資料庫分區。

錯誤代碼與傳回碼

發生錯誤時,若 DB2 文件定義了錯誤代碼,例程(使用者定義函數與預存程序)將傳回該代碼。此外,例程亦傳回自訂代碼:

  • 成功傳回 0,但 NEXT_ITEM_TYPE 成功時傳回正的 5 位數值,各數值代表一種資料類型:
數值資料類型
99388time
99384date
99392timestamp
99452char(最多 254 字元)
99448varchar(最多 32,631 字元)
99500smallint
99496int
99492bigint
99484double
  • 使用者定義函數遇任何錯誤均傳回 -1。
  • 預存程序除 DB2 伺服器錯誤代碼外,亦傳回自訂錯誤代碼(-9801 至 -9999),涵蓋參數非法、管道忙碌、無訊息、無開啟管道、管道非 SENT 狀態、權限不足、名稱不符、空間不足、狀態錯誤、會話已有開啟管道等情況。

安裝步驟

兩種方式實作管道功能:

  1. 使用 ....\pipe\sourceform\pipesetup.bat:
    pipesetup.bat <database-name> <SYSADM userid> <SYSADM passWord>
    範例:pipesetup.bat sample TEST TEST01
  2. 使用 ....\pipe\compiledform\putroutines.bat:
    putroutines.bat <database-name> <SYSADM userid> <SYSADM passWord>
    範例:putroutines.bat sample TEST TEST01

執行前須編輯實用程式,修改 DB2HOMEPATH 指向正確 SQLLIB 路徑,以及 delayUDF.jar 的實際路徑。

測試步驟

  1. 開啟兩個 DB2 COMMAND WINDOW 會話(Session A、Session B),以 SYSADM 連接範例資料庫(無則用 db2sampl 建立)。若管道系統未建立,先依上述安裝。重複測試前需刪除舊管道:
    db2 delete from dbms_pipe.pipes where pname='ABC'
  2. Session A:
    定位至 .....\pipe\testscripts,執行 db2 -td@ -f send_packet.sql 編譯建立管道、封裝兩訊息並發送的預存程序。
    執行 db2 call dbms_pipe.send_packet(),應見傳回狀態 0。
    查詢 dbms_pipe.pipes 與 dbms_pipe.pipemembers 檢視詳情。
  3. Session B:
    同目錄執行 db2 -td@ -f read_packet.sql 編譯接收、檢查、解包並關閉管道的預存程序。
    執行 db2 call dbms_pipe.read_packet(?, ?),應見傳回狀態 -999010(管道關閉後傳回),並取得 DATA1(time) 與 DATA2(date) 資料。
    同樣查詢兩目錄表檢視詳情。

重要提示

整個實作使用 DB2 UDB 錯誤訊息發送機制處理 SQL 錯誤或系統意外問題。除此,亦提供管道功能專屬的自訂錯誤代碼與傳回碼。所有錯誤(邏輯、SQL、系統)均以預存程序或函數的傳回碼(數值)捕捉。管道邏輯錯誤使用 -98XX 與 -99XX 系列,DB2 UDB 無對應實作。僅 dbms_pipe.next_item_type 傳回 5 位數值代碼檢查資料類型,搭配 dbms_pipe.unpack_message_x 採取行動。99XXX 系列與 DB2 UDB 錯誤訊息無衝突。錯誤代碼定義內嵌於各原始碼檔案,實作時可彈性選擇自訂代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved