大型 DB2 環境多應用競爭資源,鎖機制保障資料完整性。隨應用增多複雜化,診斷鎖爭用極耗時。V9.7 前僅能用 SNAP_GET_LOCKWAIT、GET SNAPSHOT FOR LOCKS、SYSIBMADM.SNAPLOCKWAIT 即時查詢,無法捕捉已超時/死鎖回滾的應用上下文(鎖模式、鎖物件、觸發 SQL)。
棄用建議:不再推薦死鎖事件監視器(CREATE EVENT MONITOR FOR DEADLOCKS、DB2DETAILDEADLOCK)與鎖超時回報(DB2_CAPTURE_LOCKTIMEOUT)。新資料庫預設仍建立 DB2DETAILDEADLOCK,建議刪除:
SET EVENT MONITOR DB2DETAILDEADLOCK STATE 0;
DROP EVENT MONITOR DB2DETAILDEADLOCK;
V9.7 新寫入目標,效能優於傳統表。事件以二進制寫入,一事件可能多列(不同 record_type)。關鍵欄位:
event_data (BLOB) - 核心資料appl_id, event_type, event_timestamp, member 等事後可用 db2evmonfmt、EVMON_FORMAT_UE_TO_XML、EVMON_FORMAT_UE_TO_TABLES 解析。本文採用存儲過程 EVMON_FORMAT_UE_TO_TABLES。
| 參數 | 可選值與含義 |
|---|---|
| MON_LOCKWAIT | NONE / WITHOUT_HIST / WITH_HIST(保留 250 筆活動歷程) / HIST_AND_VALUES(含輸入值,不含 LOB/XML/結構化型別) |
| MON_LW_THRESH | 產生事件前等待閾值(微秒) |
| MON_LOCKTIMEOUT | 同 MON_LOCKWAIT,針對鎖超時事件 |
| MON_DEADLOCK | 同 MON_LOCKWAIT,針對死鎖事件 |
建議全設 HIST_AND_VALUES,MON_LW_THRESH=5000000(5 秒):
db2 update db cfg using MON_LOCKTIMEOUT HIST_AND_VALUES MON_DEADLOCK HIST_AND_VALUES MON_LOCKWAIT HIST_AND_VALUES MON_LW_THRESH 5000000
db2 create event monitor lockwaitevm for locking write to UNFORMATTED EVENT TABLE
db2 set event monitor lockwaitevm state 1
自動建立同名表儲存捕獲資料。
stock 授權 publicapp1(handle 7)、app2(handle 14) 同時更新 itemno=300app1 先執行未 commit 持有 X 鎖,app2 等待超過 5 秒觸發事件db2 set event monitor lockwaitevm state 0
db2 "call EVMON_FORMAT_UE_TO_TABLES('LOCKING', NULL, NULL, NULL, NULL, NULL, 'RECREATE_FORCE', -1, 'SELECT * FROM lockwaitevm ORDER BY event_timestamp')"
產生四張表:
LOCK_EVENT:事件主檔(XMLID 格式 db2LockEvent_<id>_LOCKWAIT_<timestamp>_<partition>)LOCK_PARTICIPANTS:參與者(PARTICIPANT_TYPE Requester/Owner,LOCK_MODE_REQUESTED=5 為 X 鎖,LOCK_OBJECT_TYPE=2 為列鎖)LOCK_PARTICIPANT_ACTIVITIES:參與者活動(ACTIVITY_TYPE current/past,STMT_TEXT 顯示 SQL)LOCK_ACTIVITY_VALUES:活動輸入值-- 事件概覽
SELECT substr(XMLID,1,64) XML_id, EVENT_ID, substr(EVENT_TYPE,1,32) evn_type, MEMBER, DL_CONNS, ROLLED_BACK_PARTICIPANT_NO FROM LOCK_EVENT;
-- 參與者詳情
SELECT substr(XMLID,1,64) XML_id, PARTICIPANT_NO, PARTICIPANT_TYPE, PARTICIPANT_NO_HOLDING_LK, APPLICATION_HANDLE, LOCK_WAIT_VAL, LOCK_NAME, LOCK_OBJECT_TYPE, LOCK_ATTRIBUTES, LOCK_CURRENT_MODE, LOCK_MODE_REQUESTED, LOCK_MODE, LOCK_COUNT, LOCK_HOLD_COUNT, LOCK_RRIID, LOCK_STATUS, LOCK_RELEASE_FLAGS, TABLE_FILE_ID, substr(TABLE_NAME,1,10) t_name, TABLE_SCHEMA, TABLESPACE_NAME, THRESHOLD_ID, THRESHOLD_NAME FROM LOCK_PARTICIPANTS;
-- 參與者活動 SQL
SELECT PARTICIPANT_NO, ACTIVITY_TYPE, substr(STMT_TEXT,1,256) sql_text FROM LOCK_PARTICIPANT_ACTIVITIES;
LOCK_EVENT:1 筆 LOCKWAIT 事件LOCK_PARTICIPANTS:2 筆,Requester=app2(handle 14) 要求 X 鎖,Owner=app1(handle 7) 持有 X 鎖LOCK_PARTICIPANT_ACTIVITIES:app2 正執行 UPDATE(current),app1 已完成 UPDATE(past)db2 "set current lock timeout 30"
刪除舊事件/表,建立 locktimeout 監視器。app1 更新 itemno=259,app2 同行更新等待 30 秒報 SQL0911N reason code 68(鎖超時)。
LOCK_EVENT 有兩筆:先發生 LOCKWAIT(超過 5 秒),再發生 LOCKTIMEOUTapp1 更新 itemno=300(持有資源 A)app2 更新 itemno=259(持有資源 B)app1 嘗試更新 itemno=259(請求資源 B,等待)app2 嘗試更新 itemno=300(請求資源 A,等待)→ 循環等待db2 create event monitor lockdead for locking write to UNFORMATTED EVENT TABLE
db2 set event monitor lockdead state 1
依序執行上述 3 步驟 SQL,DB2 死鎖檢測器(預設 10 秒間隔 DLCHKTIME)將發現死鎖並犧牲一受害者回滾。
HIST_AND_VALUES 獲取完整上下文MON_LW_THRESH 避免噪音EVMON_FORMAT_UE_TO_TABLES 解析為關聯表便於 SQL 分析LOCK_PARTICIPANT_ACTIVITIES 中的 current/past SQL 定位問題根因