在數據庫中,鎖的主要功能是爲了控制併發數據的完整性而引入的機制,在併發應用中出現鎖現象並不可怕,鎖現象一般分爲死鎖和鎖等待兩種情形。 html
死鎖是由於兩個併發的進程或者線程同時各自佔有一個資源,又須要佔有對方資源,但又都各不相讓形成的,這一般是由於程序在併發上考慮不周形成的。java
鎖等待則是數據庫中最普通的狀況,一各應用使用數據期間必然要加鎖,防止其餘進程或應用破壞數據,其餘進程或應用在此期間不得不等待前一個應用釋放鎖。鎖等待時間參數是可調的,但要視實際應用狀況而定,好比在網絡環境中,複雜應用環境,或者對實時性要求不高的環境中,能夠將鎖等待時間調大一些,有些狀況要調小一些。鎖等待不一樣於死鎖,死鎖屬於程序併發不當,須要調整程序併發機制,鎖等待則屬於性能問題,可能須要調整程序的sql語句。sql
不論是DB2死鎖仍是鎖等待,數據庫都有相應參數可調,也有相應的工具能夠捕獲和分析,如下是鎖處理的一般辦法。數據庫
1.查看和更改與鎖相關的主要配置參數網絡
$db2 get db cfg併發
在參數列表中尋找DLCHKTIME和LOCKTIMEOUT兩個參數。(grep -i "LOCKTIMEOUT")app
-DLCHKTIME 單位是毫秒,是DB2死鎖的間隔時間,假設該值爲10000ms,則意味着每隔10秒鐘檢查一下當前數據庫中有無死鎖存在,若有死鎖,會選擇回滾其中的某一個事務,讓另一個事務完成交易。ide
-LOCKTIMEOUT單位是秒,是鎖等待最長時間,超過該時間仍未得到鎖,則返回錯誤。函數
設置提示:工具
-缺省狀況下,LOCKTIMEOUT是-1,意味着鎖等待時間無限期,這和實際應用需求通常是不太相符的,須要將其值設爲大於0的一個數。能夠將 LOCKTIMEOUT 設置爲很短的時間值,例如 10 或 15 秒。在鎖上等待過長時間會在鎖上產生雪崩效應。
首先,用如下命令檢查 LOCKTIMEOUT 的值:
db2 "get db cfg for DBNAME"
並查找包含如下文本的行:
Lock timeout (sec) (LOCKTIMEOUT) = -1
若是值是 -1,考慮使用如下命令將它更改成 15 秒(必定要首先詢問應用程序開發者或供應商以確保應用程序可以處理鎖超時):
db2 "update db cfg for DBNAME using LOCKTIMEOUT 15"
-DLCHKTIME時間一般要設得比LOCKTIMEOUT時間小一些,不然未等發現死鎖,就會被以鎖等待超時而返回錯誤。
2.查看當前併發應用
CLP方式:
db2 list applications
或db2 list applications show detail
或 db2 list applications for database dbname [ show detail]
該命令能夠查看當前是否有多個應用在鏈接着數據庫,從而排查是否有併發的存在。
注意Application Name 和Application Id兩欄,Application Name欄列出了應用的名字,db2bp一般意味着目前有CLP在鏈接數據庫,java則意味着可能有db2cc或用戶本身的java應用在鏈接數據庫,在application Id欄中能夠看到這些應用來自於哪些機器,本機的就顯示爲 LOCAL + 用戶名 + 開始鏈接上的時間,遠程的就會顯示爲16進制的IP地址+用戶名+開始鏈接上的時間。經過排查併發應用從而消除測試中沒必要要的鎖現象。
3.查看和更改快照參數
若是在合理設置了DLCHKTIME和LOCKTIMEOUT參數仍然出現鎖現象,能夠查看快照或者建立事件監控器來分析緣由。要採用快照,首先要打開快照開關
db2 get monitor switches
輸出中將包含如下參數:
監控開關 數據庫管理器參數 註釋
BUFFERPOOL DFT_MON_BUFPOOL 緩衝區的讀寫狀況和發生時間
LOCK DFT_MON_LOCK 鎖持有,鎖等待,以及DB2死鎖的發生狀況
SORT DFT_MON_SORT Heap的使用狀況,排序性能
STATEMENT DFT_MON_STMT 語句起始時間,語句內容
TABLE DFT_MON_TABLE Measure of activity (rows read/written)
UOW DFT_MON_UOW Start/end times, completion status
TIMESTAMP DFT_MON_TIMESTAMP Timestamps
爲了觀察快照中的鎖和執行語句狀況,通常把LOCK和STATEMENT選項設爲ON,也能夠酌情把其餘開關打開,示例以下: db2 update monitor switches using lock on statement on
4.查看快照信息
-查看數據庫管理器級別快照信息
db2 get snapshot for dbm
-查看數據庫級別快照信息
db2 get snapshot for database on dbname
-查看應用級別快照信息
db2 get snapshot for application agentid appl-handler
注:appl-handler能夠從list applicaitions的輸出中獲得
-查看錶級別快照信息
db2 get snapshot for tables on dbname
注:須要把tables快照開關設爲ON纔會有做用
-查看鎖快照信息
db2 get snapshot for locks on dbname
或
db2 get snapshot for locks on for application agentid appl-handler
-查看動態sql語句快照信息
db2 get snapshot for dynamic sql on dbname
5.使用事件查看器
可使用時間查看器收集鎖事件,SQL語句事件,從而根據事件分析鎖緣由。
事件類型
使用事件監控器,首先要選定所關注的事件類型,DB2中有不少事件類型,能夠用於鎖分析的一般會用到如下三種:
DEADLOCKS
DEADLOCKS WITH DETAILS
STATEMENTS
步驟:
-建立事件監控器
create event monitor evmname for eventtype write to file ‘directory’
例:create event monitor mymonitor for deadlocks, statements
write to file ‘c:\temp’
-把事件監控器打開
接上例:
set event monitor mymonitor state 1
注:1爲打開,0爲關閉
事件監控器開始工做,當全部應用斷掉鏈接後,將事件記錄下來
-查看事件細節
db2evmon –path ‘c:\temp’
上述的相關內容就是對DB2死鎖和鎖等待兩種情形的描述,但願會給你帶來一些幫助在此方面。
補充:鎖的簡單處理
$ db2 connect to portaldb
Database Connection Information
Database server = DB2/LINUXX8664 9.7.6
SQL authorization ID = DB2INST1
Local database alias = PORTALDB
$db2 get snapshot for locks on portaldb|grep -i "Application handle"
Application handle = 46046
Application handle = 46013
Application handle = 45934
Application handle = 45776
Application handle = 26
Application handle = 45664
Application handle = 45598
強行終止鎖
$db2 force application'('45598')'
或
$db2 "force application(45598)"
監控運行時間長排序次數多讀最多運行頻率高的SQL
要想查看這些SQL,能夠經過表函數(DB2 V8)或系統管理視圖(DB2 V9)來實現。
在DB2 V9中增長了管理視圖,能夠以下使用:
查看執行時間最長的 5 個動態 SQL 語句:
查看執行頻率最高的 5 個動態 SQL 語句:
查看排序次數最多的 5 個動態 SQL 語句:
在DB2 V8中增長了表函數,能夠以下使用:
查看執行時間最長的 5 個動態 SQL 語句:
查看執行頻率最高的 5 個動態 SQL 語句:
查看排序次數最多的 5 個動態 SQL 語句:
若是發現了運行成本比較高的SQL,就要來優化這些SQL的執行效率,來下降持有鎖的鎖產生的資源消耗,進一步下降死鎖和鎖等待的產生。
注意:死鎖是無法保證100%避免的,但能夠作到儘可能避免,在必定程度上減小死鎖。死鎖的頻繁發生主要須要從應用角度入手,好比選擇合適的隔離級別,是否對錶採用樂觀鎖,以及將對於同一張表的操做放到不一樣的時間上執行等方法。