每一個 DB2 鎖物件都具備四大基本屬性:Object(鎖定對象)、Size(鎖定粒度)、Duration(持有期限)、Mode(鎖模式)。掌握這四個屬性的運作邏輯,能從根本上理解並發控制行為,精準診斷鎖等待與死結問題。
Object 屬性精確標識被鎖定的資料資源。DB2 支援多層次鎖定對象:
| 層級 | Object 範例 | 說明 |
|---|---|---|
| 表空間 | TBSP_ID = 3 | DDL 操作、表空間備份/恢復時 |
| 表 | TABLE_ID = 1024 (SCHEMA.TABLE) | 最常見層級,意圖鎖與非意圖鎖均在此 |
| 資料分區 | DATA PARTITION = 5 | 分區表獨立維護 |
| 資料列 | RID = (PageID, SlotID) | 最細粒度,透過 Row Identifier 定位 |
| 索引鍵 | INDEX_KEY = (IndexID, KeyValue) | 索引掃描、唯一性檢查、Next-Key 鎖 |
| 資料頁 | PAGE_ID = 12345 | 大型機 z/OS 平台特有 |
-- db2pd -locks showdetail 輸出片段
Lock Name: 0x0004000A0000000000000000524F5753 -- 內部編碼
Type: Row -- Object 類型
Table: SCHEMA.EMPLOYEE
Row ID: 000000030012 -- Page 3, Slot 18
Mode: X
Owner: Appl Handle 47
Size 定義單一鎖物件涵蓋的資料量,直接決定鎖的粒度與並發度:
| Size 值 | 涵蓋範圍 | 並發影響 | 記憶體開銷 |
|---|---|---|---|
| Table | 整張表所有列 | 最低(全表阻塞) | 極低(單一鎖結構) |
| Data Partition | 單一分區資料 | 中等 | 低 |
| Row | 單一資料列 | 最高(列級隔離) | 高(每列一鎖結構) |
| Index Key | 單一索引鍵值 | 高 | 高 |
Duration 決定鎖被釋放的時機,主要由隔離級別與SQL 操作類型共同決定:
| 隔離級別 | 讀取鎖 Duration | 寫入鎖 Duration | 備註 |
|---|---|---|---|
| UR | Instant(即時釋放) | N/A(不加讀鎖) | 髒讀,最高並發 |
| CS | Cursor Position(游標移離釋放) | Commit/Rollback | 預設級別,平衡點 |
| RS | Transaction(交易結束釋放) | Commit/Rollback | 可重複讀,防幻讀 |
| RR | Transaction + Range Lock | Commit/Rollback | 最高隔離,鎖最多 |
Mode 是最複雜的屬性,定義擁有者權限與並發者權限的矩陣。已在「DB2 鎖機制深度解析」一文詳細列出完整模式體系,此處補充核心決策邏輯:
SQL 操作類型
├── 純讀取 (SELECT)
│ ├── UR 隔離 → IN (表) / 無 (列)
│ ├── CS/RS/RR 讀取 → IS (表) + S/NS (列)
│ └── SELECT FOR UPDATE → IX (表) + U (列)
├── 修改 (INSERT/UPDATE/DELETE)
│ └── 所有隔離級別 → IX (表) + X/WE/NX (列)
├── 顯式鎖表
│ ├── LOCK TABLE ... IN SHARE MODE → S (表)
│ ├── LOCK TABLE ... IN EXCLUSIVE MODE → X (表)
│ └── DDL (CREATE/DROP INDEX, REORG) → Z (表)
└── 內部操作
├── 索引掃描範圍鎖 → NX/NW (下一鍵)
└── 死結預防預鎖 → U (更新意圖)
當應用 A 等待應用 B 釋放鎖時,監控輸出呈現完整屬性鏈:
-- 等待者
Appl Handle: 52
Waiting for Lock:
Object: Table SCHEMA.ORDERS (Table ID 2048)
Size: Row
Mode: X
Duration: Transaction
Held by: Appl Handle 47
-- 持有者
Appl Handle: 47
Holding Lock:
Object: Table SCHEMA.ORDERS (Table ID 2048)
Size: Row
Mode: X
Duration: Transaction
Status: Executing (或 Lock Wait)
-- 1. 找出阻塞鏈頭
WITH blockers AS (
SELECT agent_id, substr(appl_name,1,20) AS appl,
lock_mode, lock_object_type, lock_object_name,
lock_status, wait_time
FROM TABLE(MON_GET_APPL_LOCKWAIT(NULL, -2))
WHERE lock_wait_time > 0
)
SELECT * FROM blockers;
-- 2. 鎖記憶體使用排行
SELECT agent_id, lock_count, lock_memory_bytes/1024/1024 AS lock_mem_mb
FROM TABLE(MON_GET_APPL_LOCKWAIT(NULL, -2))
ORDER BY lock_memory_bytes DESC FETCH FIRST 10 ROWS ONLY;
-- 3. 表級鎖升級候選者
SELECT tabschema, tabname, lock_mode, lock_count
FROM TABLE(MON_GET_TABLE_LOCK_WAIT(NULL, -2))
WHERE lock_mode IN ('X','S','Z') AND lock_count > 1000;
Object 是「誰」(哪個資源)
Size 是「多大」(粒度)
Duration 是「多久」(生命週期)
Mode 是「怎麼鎖」(權限矩陣)
四屬性合一,鎖行為盡在掌握中