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

DB2 預存程序動態日誌框架:C 語言實作、共享記憶體與生產環境最佳實踐

     編輯:DB2 教學

前言

為了在生產環境動態開啟/關閉預存程序日誌、歸檔管理、多代理程式並行寫入不衝突,本文提出一套基於共享記憶體的 C 語言日誌框架,包含管理預存程序(UPDATE_SP_CONFIG、GET_SP_CONFIG、GET_SP_LOG)與記錄預存程序(OPEN_LOG、LOGINFO、LOGGER、CLOSE_LOG),並支援 SQL-PL 與外部 C 預存程序直接呼叫。

架構設計

  • 共享記憶體:儲存所有日誌標記配置,各 DB2 代理程式映射同一區域,實現跨程序配置共享與即時生效。
  • 雜湊表+鏈結串列:以標記名雜湊值為索引,同雜湊值標記形成鏈結串列,O(1) 查詢配置參數。
  • 日誌檔案歸檔:超過大小限制自動移至 archive 目錄,避免單一檔案過大。
  • 分離/合併模式:LOG_SPLIT=Y 依應用程式 ID 建立獨立日誌檔;=N 合寫 sp.log 並以應用程式 ID 區分。

核心預存程序

預存程序用途關鍵參數
DB2.UPDATE_SP_CONFIG設定/更新標記配置(全域與私有)log_token_name, value (Y/N/R)
DB2.GET_SP_CONFIG查詢目前所有標記與除錯模式無
DB2.GET_SP_LOG讀取指定日誌檔內容回傳結果集log_file_name
DB2.OPEN_LOG啟動日誌,取得 48 位元組句柄log_token_name, handle CHAR(48) FOR BIT DATA
DB2.LOGINFO記錄資訊層級訊息(標記存在即寫入)handle, message
DB2.LOGGER記錄除錯層級訊息(需標記 DEBUG=Y)handle, message
DB2.CLOSE_LOG關閉日誌,記錄經過時間handle

配置管理實戰

-- 全域開關
CALL DB2.UPDATE_SP_CONFIG('GLOBAL_LOGGING','Y');  -- 啟用
CALL DB2.UPDATE_SP_CONFIG('GLOBAL_LOGGING','N');  -- 關閉

-- 日誌分離
CALL DB2.UPDATE_SP_CONFIG('LOG_SPLIT','Y');       -- 依代理分檔
CALL DB2.UPDATE_SP_CONFIG('LOG_SPLIT','N');       -- 合併寫入

-- 私有標記(以 TESTSP 為例)
CALL DB2.UPDATE_SP_CONFIG('TESTSP','Y');  -- 建立並啟用除錯
CALL DB2.UPDATE_SP_CONFIG('TESTSP','N');  -- 停用除錯(保留標記)
CALL DB2.UPDATE_SP_CONFIG('TESTSP','R');  -- 移除標記(含配置檔與共享記憶體)

配置檔 .splogrc 位於 ~/sqllib/splog/<dbname>/,DBA 需預先建立目錄並授權 fenced user 讀寫。

SQL-PL 預存程序使用範例

CREATE PROCEDURE TESTSP()
LANGUAGE SQL
BEGIN
  DECLARE h CHAR(48) FOR BIT DATA;
  DECLARE cnt INT DEFAULT 0;
  CALL DB2.OPEN_LOG('TESTSP', h);
  SET cnt = cnt + 1;
  CALL DB2.LOGINFO(h, 'loginfo ' || CHAR(cnt));
  SET cnt = cnt + 1;
  CALL DB2.LOGGER(h, 'logger ' || CHAR(cnt));
  -- 更多記錄...
  CALL DB2.CLOSE_LOG(h);
END

日誌輸出範例:

12-25-2005 22:29:39.839:[testsp:051226021028] Begin Stored Procedure *** [681574408]
12-25-2005 22:29:39.839:[testsp:051226021028] loginfo 1
12-25-2005 22:29:39.839:[testsp:051226021028] logger 2
...
12-25-2005 22:29:39.839:[testsp:051226021028] End Stored Procedure *** Elapsed 0.000

C 語言外部預存程序直接呼叫 API

#include "logger.h"
#define BYTEHANDLESIZE 48

void openLog(char *name, char *handle);
void closeLog(char *handle);
void setDBName(struct sqludf_dbinfo *dbInfo);
void logger(char *handle, char *fmt, ...);
void logginfo(char *handle, char *fmt, ...);

範例:

SQL_API_RC SQL_API_FN Snow(..., struct sqludf_dbinfo *dbInfo) {
  char byteHandle[BYTEHANDLESIZE];
  setDBName(dbInfo);                    // 必須先呼叫以設定資料庫名
  openLog("TESTSP", byteHandle);
  logger(byteHandle, "DB name: %s", dbInfo->dbname);
  logger(byteHandle, "HOME: %s", getenv("HOME"));
  logger(byteHandle, "Appl ID: %s", dbInfo->appl_id);
  closeLog(byteHandle);
  return 0;
}

註冊時需指定 DBINFO 選項以取得 dbInfo 結構。

部署與維運關鍵

  • 編譯:使用 ~/sqllib/samples/c/bldrtn、embprep(平台專屬版本),而非原始碼附帶腳本。
  • KEEPFENCED=YES:共享庫常駐記憶體,更新需重命名庫並 ALTER PROCEDURE ... EXTERNAL NAME 'newlib!func'(見 spalter 腳本)。
  • 共享記憶體釋放:日誌開啟行顯示的數字為共享記憶體 ID,可用 ipcrm -m <id> 釋放(需 fenced user 身分)。
  • 常見問題:日誌不出現多為目錄權限問題;磁碟滿導致停止寫入;Windows/Solaris 平台尚未測試。

效能優化建議

  • 全域關閉:CALL DB2.UPDATE_SP_CONFIG('GLOBAL_LOGGING','N') 即時生效,零負擔。
  • 程式碼層面移除:上線前以 sed 's/CALL DB2./--CALL DB2./' 批次註解所有日誌呼叫,保留原始碼以便未來啟用。

結語

此框架提供生產級動態日誌能力:零停機切換、多代理隔離、共享記憶體高效配置同步、彈性歸檔。開發團隊可視專案需求採用整套或部分元件,將預存程序可觀測性納入標準交付流程。

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