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

DB2 生產環境死鎖完整排查實錄:從無法重現到鎖定 cur_commit 參數

     編輯:DB2 綜合知識

前言

生產環境 DB2 出現「單純 SELECT 陳述式頻繁死鎖」的詭異現象,且無法在測試環境重現。本文完整記錄 8 階段排查過程,最終鎖定 cur_commit 設定差異為根因,並給出索引解決方案。

一、現象描述

  • 特定 SELECT SQL 在高併發時頻繁噴 SQL0911N (死鎖/逾時)。
  • 該 SQL 無大量資料處理、無複雜連接,僅單表查詢。
  • 傳統經驗:死鎖通常發生於 UPDATE/DELETE,SELECT 極少見。

二、八階段排查歷程

階段 1:懷疑資料量導致系統負載過高

  • 蒐集 CPU、磁碟 I/O、網路、記憶體等指標 → 無異常峰值。
  • 結論:非資源耗盡導致。

階段 2:多執行緒模擬併發測試

  • 編寫多執行緒程式模擬多用戶同時執行該 SQL → 測試環境無法重現死鎖。

階段 3:對比測試/生產環境資料量

  • 盡量複製生產資料量至測試庫 → 仍無法重現。

階段 4:分析用戶操作日誌

  • 發現「兩位用戶同時操作」時極高機率死鎖。
  • 推測為併發衝突,但測試環境同樣模擬併發卻無事。

階段 5:發現資料庫參數設定差異

  • 對比 db2 get db cfg 輸出,聚焦含 LOCK 關鍵字的參數 → 多處不一致。
  • 逐一調整測試環境參數與生產一致 → 仍無法重現。

階段 6:關鍵參數 cur_commit 浮現

  • 注意到 cur_commit (Currently Committed) 設定不同:
    生產 = OFF、測試 = ON。
  • 查閱文件:cur_commit=OFF 時,「交易 A 插入資料 → 交易 B 插入資料 → 交易 B 未提交前交易 A 查詢同表」會導致死鎖。

階段 7:調整參數並重現

  • 測試環境設定 db2 update db cfg using cur_commit OFF 並重啟實例。
  • 修改測試程式模擬上述兩交易時序 → 成功重現死鎖,錯誤碼與生產完全一致。

階段 8:實際畫面操作驗證

  • 透過應用程式介面雙人同時操作 → 死鎖重現,確認根因無誤。

三、根因分析:cur_commit 機制

設定行為死鎖風險
cur_commit = ON (預設 9.7+)讀取者可存取「目前已提交」版本資料列,不等待未提交寫入鎖釋放低
cur_commit = OFF讀取者遇到未提交寫入鎖會等待,若雙方互相等待 → 死鎖高

生產環境為舊版升級而來,保留 OFF 設定;測試環境全新安裝預設 ON,導致行為差異。

四、解決方案

  1. 建立索引:在 WHERE 條件欄位上建立索引,使查詢走索引存取而非全表掃描,大幅縮短鎖持有時間與掃描範圍 → 死鎖消失。
  2. 啟用 cur_commit ON (次選):
    db2 update db cfg using cur_commit ON
    db2stop force; db2start
    

    需評估相容性:舊應用若依賴「讀取等待未提交寫入」語意可能行為改變。

五、經驗總結

  1. 參數基線管理:生產/測試/開發環境 DB 參數必須版本化、基線化,任何差異皆為潛在風險。
  2. 死鎖不只寫寫衝突:在 cur_commit=OFF 下,「讀寫」也會死鎖。
  3. 無法重現 ≠ 無問題:環境差異 (參數、資料分佈、統計資訊) 可能完全改變並發行為。
  4. 索引是最經濟的鎖降級手段:縮小掃描範圍 → 減少鎖粒度 → 降低衝突機率。

結語

這次排查耗時數週,核心教訓是「環境一致性」先於「程式碼分析」。建立參數基線、自動化環境驗證、善用 db2pd -locks 與 db2trc 進行即時診斷,才能在下次類似事件中快速定位根因。

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