《記一次生產DB2數據庫鎖超時問題的分析與排查》要點:
本文介紹了記一次生產DB2數據庫鎖超時問題的分析與排查,希望對您有用。如果有疑問,可以聯系我們。
作者介紹
侯君,證通股份有限公司DBA,主要負責DB2、MySQL、Couchbase運維,以及自動化運維平臺開發,Python愛好者.
前言
DB2的鎖管理機制一直為DB2應用開發人員和DBA所詬病.對其鎖機制不理解的直接后果就是導致鎖超時和死鎖的發生.所以監控并分析鎖超時和死鎖,應是每個DB2 DBA的居家必備生存技能.本文記錄了公司生產環境數據庫發生鎖超時后的分析、處理過程,如有表述不當之處,歡迎指正.
DB2?pureScale V10.5 FP5.
我司生產環境某數據庫每天下午15:40~15:50會報鎖超時.經查明,問題發生時間正好是每日集中跑批時間.
為了能抓到鎖超時的Requestor和Owner,需要對數據庫進行適當配置.
設置TIMEOUT注冊變量
db2set DB2_CAPUTRE_LOCKTIMEOUT=ON
一旦發生鎖超時,會在~/sqllib/db2dump/DIAG000{0,1}/路徑下面生成 db2locktimeout.1.5493.2017-05-25-15-49-01 文件.
設置db2cos
僅有db2locktimeout*文件中的信息不足以定位Lock Requestor的具體語句.因此,我們在生產環境還啟用了db2cos腳本,捕獲更詳細的應用信息.該腳本位于?~/sqllib/bin/db2cos中.
我們對觸發命令進行了改造,以便抓取更多信息:
#號注釋的命令為原始命令,此處替換成下一行的新內容.
修改完腳本后,執行以下命令使腳本生效:
db2pdcfg -catch 911,68 count=255
一旦發生鎖超時,便會觸發db2cos腳本,在DIAG目錄下面生成捕獲的文件,
格式為:$pid.$eduid.$dbpart.db2pd.${database}.txt
例如:202484.5493.001.db2pd.PTSMGMDB.txt
首先分析db2locktimeout.1.5493.2017-05-25-15-49-01 報告的內容:
報告里描述了Lock Requestor和Lock Owner詳細信息,包括鎖超時發生時間,鎖類型(Table lock)和加鎖的資源ID(obj={4;136}).通過表和表空間ID,我們可以執行以下語句定位被鎖的表名:
Lock Requestor應用程序名稱為db2bp,它是CLP后端進程的名稱.但是在db2locktimeout文件中,我們看不到Requestor的語句,這個可以通過查看db2cos腳本抓到的202484.5493.001.db2pd.PTSMGMDB.txt文件得到.
再來看Lock Owner,顯示占用表的應用是package,可以知道package的名字PTSDAYOFFPUB和版本號V1.1.0_P25,并且當時執行了兩條SQL語句11和12,可以通過SYSCAT.STATEMENTS查找執行語句內容,但是因為此查詢可能會導致嘗試更新SYSCAT.STATEMENTS目錄視圖的其他應用程序發生競爭,所以查詢時最好使用UR隔離級別.
可以發現只有編號位11的查詢table是T_BASE_QWDZLSB?,因此可以確定該語句導致了對表加鎖,其隔離級別為CS,會產生一個IS鎖.
再來看下202484.5493.001.db2pd.PTSMGMDB.txt,定位Lock Requestor語句,原始文件中內容很多,我們對其進行了剪裁,提取出關鍵部分.
首先看Locks:段的信息:
TranHdl?287的Sts為G,表明占有鎖;TranHdl?272的Sts為W*,表明正在等待.接著根據Locks being waited on:段映射TranHdl和AppHandl,知道272的AppHandl為111774?.
而111774?當前執行語句信息為C-AnchID和C-StmtUID為781和1,根據這兩個值定位到Dynamic SQL Statements:段
可以發現執行語句為LOCK TABLE t_base_qwdzlsb IN EXCLUSIVE MODE .
同樣可以在Application:段中查看更詳細信息:
至此,可以總結導致鎖超時的root?cause:
PTSDAYOFFPUB執行了SELECT * from T_BASE_QWDZLSB語句,對表加了IS鎖;而后在CLP中又執行了LOCK TABLE t_base_qwdzlsb IN EXCLUSIVE MODE語句(之后發現由IMPORT操作引起),請求一個X表鎖.而IS和X鎖是不兼容的,X鎖會一直等待IS鎖釋放,超過系統設置的30秒超時時間,從而發生鎖超時.
1、定位造成鎖超時的語句后,我們讓項目組修改了package中的查詢游標,加上WITH UR,但是鎖超時依舊在報?這是為什么呢?
因為雖然顯式地指定了SQL 語句的隔離級別為UR,但是,由于DB2中的游標是模糊游標 (沒有顯式地聲明游標是只讀的還是可更新的),因而系統會默認地將這個模糊游標當成可更新游標處理,在 UR 下,可更新游標的工作方式就像隔離級別為CS一樣.要避免這種升級,可以采用以下辦法:
修改應用程序中的游標,使游標變成非模糊游標.將 SELECT 語句更改為SELECT * from table_name FOR READ ONLY?WITH UR子句.
2、在報告中看到了Lock Requestor的LOCK TABLE語句,未在腳本或程序里發現,是什么引起的?
經過分析,發現該語句是由IMPORT Utility引起.
IMPORT支持兩種表鎖定方式:脫機或ALLOW NO ACCESS方式;以及聯機或ALLOW WRITE ACCESS方式.ALLOW NO ACCESS方式會阻止并行應用程序訪問表數據,ALLOW WRITE ACCESS方式允許并行應用程序同時對導入目標表進行讀寫訪問.如果未顯示指定任何方式,那么IMPORT默認為ALLOW NO ACCESS,同時,默認情況下會使用RS綁定數據庫,因此可以改造IMPORT語句:
IMPORT?FROM xx.ixf of ixf ALLOW WRITE ACCESS COMMITCOUNT 5000 INSERT INTO table_name
如上所述分析鎖超時的步驟還是很繁瑣的,而且需要一定的技巧和概念基礎,需要:
但只要多分析,多查資料,就可以將整個分析過程進行流程化,后期就能和自動化運維工作結合起來.
原文來自微信公眾號:DBAplus社群
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/2703.html