天天看點

知方可補不足~用SqlProfiler來監視資料庫死鎖

回到目錄

關于鎖的相關知識,大家可以看我的這篇文章《知方可補不足~Sqlserver中的幾把鎖和.net中的事務級别》

死鎖我想大家都知道,當一個對話(線程)占用一個資源時,别一個線程也同時去通路它,并且其中一個優化級高的對話将SQL鎖狀态提升為X鎖(排它鎖)後,其一個對話将會被作為“犧牲品”抛棄,這種現象在SQLSERVER中就叫做死鎖,引起死鎖的原因有很多,一般在網上被前人總結為四點

1、互斥使用(資源獨占)

 一個資源每次隻能給一個程序使用

2、不可強占(不可剝奪)

    資源申請者不能強行的從資源占有者手中奪取資源,資源隻能由占有者自願釋放

3、請求和保持(部分配置設定,占有申請)

一個程序在申請新的資源的同時保持對原有資源的占有(隻有這樣才是動态申請,動态配置設定)

4、循環等待

存在一個程序等待隊列     {P1 , P2 , … , Pn},     其中P1等待P2占有的資源,P2等待P3占有的資源,…,Pn等待P1占有的資源,形成一個程序等待環路

觀察鎖的發生,使用sqlProfiler工具

設定對話(線程,spid)的優先級

SET TRANSACTION ISOLATION LEVEL Read Committed
BEGIN TRAN
SET DEADLOCK_PRIORITY HIGH      

對于優先級,以以下選項

 LOW | NORMAL | HIGH

也可以直接使用數字

<numeric-priority> ::= { -10 | -9 | -8 | …| 0 | …| 8 | 9 | 10 }

在EF裡,對發生死鎖的代碼進行重新送出

在EF架構裡,倉儲大叔提倡大家使用自己的SaveChanges方法,其原因就是可以對送出動作進行統一的控制,在裡面加日志,加捕捉,加政策可以成為可能,呵呵。

 //下面代碼節選自大叔的DbContextRepository類
  catch (EntityException ex)//EF配置異常,這個異常可以忽略(The underlying provider failed on Commit.)
            {
                if (Logger != null)
                    Logger(ex.Message);
                throw new Exception(ex.Message);//EntityException
            }
            catch (Exception ex)//捕獲所有異常
            {

                if (Logger != null)//如果沒有定義日志功能,就把異常抛出來吧
                    Logger(ex.Message + "處理時間:" + DateTime.Now);
                if (ex.GetBaseException() != null
                    && ex.GetBaseException().GetType() == typeof(System.Data.SqlClient.SqlException))
                {
                    //SqlException異常,再重新進行送出
                    Db.SaveChanges();
                }
                throw new Exception(ex.Message);
            }      

作者:倉儲大叔,張占嶺,

榮譽:微軟MVP

QQ:853066980

支付寶掃一掃,為大叔打賞!

知方可補不足~用SqlProfiler來監視資料庫死鎖