回到目錄
關于鎖的相關知識,大家可以看我的這篇文章《知方可補不足~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
支付寶掃一掃,為大叔打賞!