鎖是關聯式資料庫實現 ACID 隔離性的核心機制。DB2 採用多粒度鎖架構,支援表空間、表、資料列、索引鍵等層級,配合意圖鎖協調層級間相容性,並在記憶體壓力下自動執行鎖升級。深入理解鎖機制是解決並發效能問題、避免死結的關鍵。
鎖的基本屬性
| 屬性 | 說明 |
| Object | 被鎖定資源:表空間、表、列、索引鍵、資料頁(大型機) |
| Size | 鎖定範圍大小:表級 vs 列級 |
| Duration | 持有時間:由隔離級別決定(CS 提交釋放、RR 交易結束釋放) |
| Mode | 鎖模式:決定擁有者與並發存取者的權限 |
DB2 完整鎖模式體系(按控制強度遞增)
表級意圖鎖(需配合列級鎖)
| 模式 | 全稱 | 擁有者權限 | 並發者權限 | 典型場景 |
| IN | Intent None | 讀取(含未提交資料),不可修改 | 可讀可改 | UR 隔離級別掃描表 |
| IS | Intent Share | 讀取,列級加 S 鎖 | 可讀可改 | CS/RR/RS 讀取操作 |
| IX | Intent Exclusive | 讀取(列S) + 修改(列X/U) | 可讀可改 | INSERT/UPDATE/DELETE、SELECT FOR UPDATE |
| SIX | Share With Intent Exclusive | 讀取 + 修改(列X),不加列S | 僅可讀取 | 大量讀取後少量修改 |
表級非意圖鎖(不需列級鎖,排他性強)
| 模式 | 全稱 | 擁有者權限 | 並發者權限 | 典型場景 |
| S | Share | 讀取全表 | 僅可讀取(可加 S/IS) | LOCK TABLE ... IN SHARE MODE |
| U | Update | 讀取全表,稍後升級為 X | 僅可讀取(可加 S/IS) | 預備修改,避免 S→X 死結 |
| X | Exclusive | 讀寫全表 | 僅 UR 可讀 | LOCK TABLE ... IN EXCLUSIVE MODE、DDL |
| Z | Super Exclusive | 結構變更(DROP/CREATE INDEX、REORG) | 完全阻擋(含 UR) | DDL、REORG、LOAD REPLACE |
列級鎖模式
| 模式 | 全稱 | 說明 |
| NS | Next Key Share | RS/CS 讀取時的列鎖,避免幻讀 |
| S | Share | 讀取列,RR/RS/CS 共享讀 |
| NX | Next Key Exclusive | 索引插入/刪除時對下一鍵加鎖防幻讀 |
| NW | Next Key Weak Exclusive | 非目錄表索引插入時的下一鍵鎖 |
| X | Exclusive | 修改列(UPDATE/DELETE/INSERT) |
| WE | Weak Exclusive | 非目錄表插入列鎖 |
鎖相容性矩陣(核心子集)
✅ = 相容 | ❌ = 衝突
| 既有鎖\申請鎖 | IS | IX | S | U | X | Z |
| IS | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| IX | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| S | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| U | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| X | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Z | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
關鍵洞察:U 鎖與 S 鎖衝突,解決「雙方持 S 同時申請 X」的死結經典問題。
隔離級別與鎖持有期對應
| 隔離級別 | 讀取列鎖 | 釋放時機 | 幻讀防護 |
| UR (Uncommitted Read) | 無(或 IN) | 即時 | 無 |
| CS (Cursor Stability) | S / NS | 游標移離/提交 | 部分(NS) |
| RS (Read Stability) | S / NS | 交易結束 | 有(掃描範圍鎖) |
| RR (Repeatable Read) | S / NX | 交易結束 | 完全(範圍鎖/下一鍵鎖) |
鎖升級機制
觸發條件(任一滿足即觸發)
- 應用程式層級:單一應用持有鎖記憶體 >
MAXLOCKS% × LOCKLIST
- 資料庫層級:全資料庫鎖記憶體總和 >
LOCKLIST
關鍵配置參數
LOCKLIST = 10000 -- 4KB 頁數,預設值視版本而異,建議 50000+ (200MB+)
MAXLOCKS = 22 -- 單應用佔用上限百分比,建議 30-50
升級過程
- 嘗試為觸發應用申請表級非意圖鎖(S/U/X)
- 成功則釋放該應用所有列級鎖
- 失敗(如與其他應用表級鎖衝突)→ 回傳 SQL0912N(鎖升級失敗)
升級失敗應對
- DBA:增加
LOCKLIST、調大 MAXLOCKS
- 開發:捕捉
SQLCODE=-912 → ROLLBACK → 重試邏輯
- 設計:縮短交易、批次提交、避免長交易掃描大量資料
監控與診斷
快照監控(低負擔)
db2 "get snapshot for locks on "
db2 "get snapshot for applications on | grep -A 5 'Locks held'"
db2pd 即時診斷(無鎖競爭)
db2pd -db -locks showdetail
db2pd -db -agents | grep -E 'Lock|State'
事件監控(深度分析,高負擔)
db2 "create event monitor lockmon for deadlocks with details write to file '/db2/lockmon'"
db2 "set event monitor lockmon state 1"
-- 重現死結後
db2 "set event monitor lockmon state 0"
db2evmon -path /db2/lockmon > deadlock.rpt
死結預防最佳實務
- 固定存取順序:所有交易按相同順序存取表(如按表名字母序)
- 縮短交易:提交前不做用戶互動、外部 API 呼叫
- 使用 U 鎖語意:
SELECT ... FOR UPDATE 明確申請 U 鎖
- 避免升級為表鎖:調大 LOCKLIST/MAXLOCKS、分批處理大量資料
- 設定鎖等待逾時:
db2 update db cfg using LOCKTIMEOUT 30(秒),避免無限等待