啟用 LOGRETAIN=ON (或 LOGARCHMETH1) 後,DB2 進入可恢復模式,支援前滾恢復。活動日誌目錄將不再自動循環覆蓋,日誌檔案持續累積,若無有效歸檔機制,將導致磁碟耗盡、資料庫掛起。本文深度解析三類日誌生命週期、手工與自動化 (USEREXIT) 歸檔方案、跨平台部署細節與監控告警體系。
| 日誌類型 | 定義 | 狀態 | 存放位置 | 清理機制 |
|---|---|---|---|---|
| 活動日誌 | 包含未提交/未回滾交易、已提交但未寫入資料頁的交易 | Active | LOGPATH / NEWLOGPATH | 交易提交 + 檢查點完成 + 不被任何應用需要 → 轉為聯機歸檔 |
| 聯機歸檔日誌 | 所有交易已提交且寫入資料頁,但仍在活動日誌目錄中 | Online Archived | 同活動日誌目錄 | USEREXIT 歸檔成功 → 標記可刪除 → DB2 自動刪除或手工清理 |
| 離線歸檔日誌 | 已從活動目錄複製至異地/備份儲存的日誌 | Offline Archived | 歸檔路徑 (磁帶/NFS/TSM/Object Storage) | 依保留策略過期刪除 (前滾恢復仍可能需要) |
關鍵流程:Active → (Checkpoint + Log Archiver) → Online Archived → (USEREXIT/手工複製) → Offline Archived → (Retention Expire) → Delete
# 1. 確認聯機歸檔日誌 (已歸檔但未離線)
db2 "select * from table(mon_get_transaction_log(-2)) where log_type='ARCHIVED'"
# 2. 複製至歸檔目的地 (需資料庫非獨佔鎖定)
cp /db2log/NODE0000/LOGSTREAM0000/S0000001.LOG /archive/db2logs/MYDB/
# 3. 標記日誌可刪除 (DB2 10.1+)
db2 "call sysproc.admin_cmd('archive log for database MYDB')"
# 或舊版: db2 "archive log for database MYDB"
# 4. 驗證清理
ls -l /db2log/NODE0000/LOGSTREAM0000/
缺點:人工介入、易遺漏、無法應對高日誌產生速率、無錯誤重試機制。生產環境強制要求自動化。
user exit 程式 (可執行檔/腳本)# 1. 定位範例程式碼
ls /opt/ibm/db2/V11.5/bin/user_exit.rc
# 或
ls /opt/ibm/db2/V11.5/samples/c/user_exit.c
# 2. 編譯 (C 版本,效能最佳)
cd /opt/ibm/db2/V11.5/samples/c
xlc_r -o user_exit user_exit.c # AIX
gcc -o user_exit user_exit.c # Linux
# 3. 部署至實例 bin 目錄 (DB2 會自動尋找)
cp user_exit /home/db2inst1/sqllib/bin/
chmod 755 /home/db2inst1/sqllib/bin/user_exit
chown db2inst1:db2iadm1 /home/db2inst1/sqllib/bin/user_exit
# 啟用歸檔 (二選一,LOGARCHMETH1 為現代語法)
db2 update db cfg for MYDB using LOGRETAIN ON
# 或
db2 update db cfg for MYDB using LOGARCHMETH1 "DISK:/archive/db2logs/MYDB"
db2 update db cfg for MYDB using LOGARCHMETH2 "VENDOR:/home/db2inst1/sqllib/bin/user_exit"
# 關鍵效能參數
db2 update db cfg for MYDB using NUM_LOGARCH_DBS 2 # 並行歸檔進程數
db2 update db cfg for MYDB using ARCHRETRYDELAY 30 # 重試間隔 (秒)
db2 update db cfg for MYDB using FAILARCHPATH "/archive/db2logs/MYDB/fail" # 失敗暫存路徑
#!/bin/ksh
# /home/db2inst1/sqllib/bin/user_exit
# DB2 呼叫慣例: user_exit <操作> <日誌檔名> <資料庫別名> <日誌路徑>
# 操作: ARCHIVE / RETRIEVE / DELETE / INIT / TERM
OPERATION=$1
LOGFILE=$2
DBALIAS=$3
LOGPATH=$4
ARCHIVE_ROOT="/archive/db2logs/${DBALIAS}"
FAIL_DIR="${ARCHIVE_ROOT}/failed"
COMPRESS="gzip -9"
ENCRYPT="gpg --encrypt --recipient dba-team@company.com"
MAX_RETRY=3
RETRY_DELAY=10
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') [$OPERATION] $*" | tee -a /home/db2inst1/sqllib/db2dump/user_exit.log
}
archive_log() {
local src="${LOGPATH}/${LOGFILE}"
local dst="${ARCHIVE_ROOT}/${LOGFILE}.gz.gpg"
local tmp_dst="${dst}.tmp"
mkdir -p "${ARCHIVE_ROOT}"
# 壓縮 + 加密 + 原子性寫入
if ${COMPRESS} -c "${src}" | ${ENCRYPT} -o "${tmp_dst}"; then
mv "${tmp_dst}" "${dst}"
# 驗證完整性
if gpg --decrypt "${dst}" | gzip -t; then
log "SUCCESS: Archived ${LOGFILE} to ${dst}"
return 0
else
log "ERROR: Integrity check failed for ${dst}"
rm -f "${dst}"
return 1
fi
else
log "ERROR: Compression/Encryption failed for ${LOGFILE}"
return 1
fi
}
retrieve_log() {
local src="${ARCHIVE_ROOT}/${LOGFILE}.gz.gpg"
local dst="${LOGPATH}/${LOGFILE}"
if [[ ! -f "${src}" ]]; then
log "ERROR: Archive not found: ${src}"
return 1
}
if gpg --decrypt "${src}" | gzip -dc > "${dst}"; then
log "SUCCESS: Retrieved ${LOGFILE} from archive"
return 0
else
log "ERROR: Decrypt/Decompress failed for ${LOGFILE}"
rm -f "${dst}"
return 1
fi
}
case ${OPERATION} in
ARCHIVE)
retry=0
while [ $retry -lt ${MAX_RETRY} ]; do
archive_log && exit 0
retry=$((retry+1))
log "RETRY ${retry}/${MAX_RETRY} in ${RETRY_DELAY}s"
sleep ${RETRY_DELAY}
done
# 失敗移至失敗目錄供人工處理
mkdir -p "${FAIL_DIR}"
cp "${LOGPATH}/${LOGFILE}" "${FAIL_DIR}/"
log "FAILED: Moved to ${FAIL_DIR} for manual intervention"
exit 1
;;
RETRIEVE)
retrieve_log
exit $?
;;
DELETE)
# 歸檔保留策略由外部排程管理,此處通常不刪除歸檔檔
log "INFO: DELETE operation received for ${LOGFILE} (no-op)"
exit 0
;;
INIT)
log "INIT: User exit initialized for ${DBALIAS}"
exit 0
;;
TERM)
log "TERM: User exit terminated for ${DBALIAS}"
exit 0
;;
*)
log "ERROR: Unknown operation ${OPERATION}"
exit 1
;;
esac
# 使用 TSM API
db2 update db cfg for MYDB using LOGARCHMETH1 "TSM: {TSM_SERVER} {NODE_NAME} {PASSWORD}"
# 使用 VENDOR 庫 (如 NetBackup, CommVault, AWS S3, Azure Blob)
db2 update db cfg for MYDB using LOGARCHMETH1 "VENDOR:/opt/ibm/db2/V11.5/lib/libdb2vendor.so"
# 雙重歸檔 (本地磁碟 + 異地 TSM) - 強烈推薦生產環境
db2 update db cfg for MYDB using LOGARCHMETH1 "DISK:/archive/db2logs/MYDB"
db2 update db cfg for MYDB using LOGARCHMETH2 "TSM: tsm_server node_name password"
| 監控指標 | 查詢方式 | 告警閾值 | 處置動作 |
|---|---|---|---|
| 活動日誌目錄使用率 | df -h /db2log | > 80% | 檢查歸檔延遲、擴容、加速歸檔 |
| 最舊活動日誌序號 vs 當前序號 | db2pd -db MYDB -logs | 差距 > 1000 | 歸檔滯後,檢查 USEREXIT 錯誤日誌 |
| USEREXIT 失敗次數 | grep FAILED /home/db2inst1/sqllib/db2dump/user_exit.log | > 0 | 立即人工介入,檢查網路/儲存/權限 |
| 歸檔延遲時間 | db2 "select (current timestamp - archive_time) from table(mon_get_transaction_log(-2)) where log_type='ARCHIVED' order by archive_time desc fetch first 1 row only" | > 1 小時 | 歸檔效能瓶頸,調大 NUM_LOGARCH_DBS、優化壓縮/加密 |
| 日誌檔案數量 | ls /db2log/.../S*.LOG | wc -l | > 5000 | 檢查長交易、歸檔阻塞、參數 LOGPRIMARY/LOGSECOND |
ROLLFORWARD 驗證完整性DB2 日誌歸檔管理的核心原則:自動化優於手工、雙重歸檔優於單一、加密驗證優於裸傳、監控告警優於事後發現、定期演練優於臨時抱佛腳。USEREXIT 程式作為自動化核心,必須具備重試機制、完整性驗證、失敗隔離、詳細審計日誌。將歸檔基礎設施 (磁碟/TSM/雲端) 納入容量規劃與備份策略統一管理,確保在 RPO=0、RTO<分鐘的金融級要求下,日誌鏈永不斷裂,資料永不遺失。