在先前的文章〈在 DB2 通用資料庫中實現會話間警告〉中,我們介紹了如何利用兩個資料庫會話之間的警示(alert)建立通訊管道。本文將提供另一種會話間通訊的實作方式——訊息管道。警示與管道皆可在非同步與同步兩種模式下運作,但兩者有本質差異:管道能將單一訊息的分組從一個會話傳輸至另一個會話,而警示僅能觸發另一會話採取行動。透過管道,您可以實際地將由不同資料類型組成的訊息封包從一個會話傳遞至另一個會話。此實作類似 Oracle 的 DBMS_PIPE 套件,但在細節上有所不同,若您計畫將應用程式從 Oracle 移植至 DB2 Universal Database,此機制將相當實用。
此管道實作包含以下資料庫物件:
管道通訊需要兩個參與會話:會話 A 負責準備並發送訊息封包至資料庫目錄;會話 B 負責接收、讀取封包並關閉管道。
除核心通訊功能外,尚提供三項管理功能:
為支援管道功能,實作了三類資料庫物件:
DBMS_PIPE.PIPES:儲存管道定義DBMS_PIPE.PIPEMEMBERS:以純文字格式儲存訊息DBMS_PIPE.PIPEMEMBERS_ENCRYPT:以加密字串格式儲存訊息DBMS_PIPE.DELAY:提供以秒為單位的延遲DBMS_PIPE.SESSION_ID:從資料庫管理器擷取會話 ID註:這兩個函數的原始碼可參考前文〈在 DB2 通用資料庫中實現會話間警告〉,此處使用已編譯版本。
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:清除管道訊息並將狀態重設為 PACKINGDBMS_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。
發生錯誤時,若 DB2 文件定義了錯誤代碼,例程(使用者定義函數與預存程序)將傳回該代碼。此外,例程亦傳回自訂代碼:
NEXT_ITEM_TYPE 成功時傳回正的 5 位數值,各數值代表一種資料類型:| 數值 | 資料類型 |
|---|---|
| 99388 | time |
| 99384 | date |
| 99392 | timestamp |
| 99452 | char(最多 254 字元) |
| 99448 | varchar(最多 32,631 字元) |
| 99500 | smallint |
| 99496 | int |
| 99492 | bigint |
| 99484 | double |
兩種方式實作管道功能:
....\pipe\sourceform\pipesetup.bat:pipesetup.bat <database-name> <SYSADM userid> <SYSADM passWord>pipesetup.bat sample TEST TEST01....\pipe\compiledform\putroutines.bat:putroutines.bat <database-name> <SYSADM userid> <SYSADM passWord>putroutines.bat sample TEST TEST01執行前須編輯實用程式,修改 DB2HOMEPATH 指向正確 SQLLIB 路徑,以及 delayUDF.jar 的實際路徑。
db2sampl 建立)。若管道系統未建立,先依上述安裝。重複測試前需刪除舊管道:db2 delete from dbms_pipe.pipes where pname='ABC'.....\pipe\testscripts,執行 db2 -td@ -f send_packet.sql 編譯建立管道、封裝兩訊息並發送的預存程序。db2 call dbms_pipe.send_packet(),應見傳回狀態 0。dbms_pipe.pipes 與 dbms_pipe.pipemembers 檢視詳情。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 錯誤訊息無衝突。錯誤代碼定義內嵌於各原始碼檔案,實作時可彈性選擇自訂代碼。