SQL:查找被鎖的表,以及鎖表的SQL語句(重點推薦)
--死鎖檢測 use master Select * from sysprocesses where blocked<>0 --找到SPID exec sp_lock --根據SPID找到OBJID select object_name(85575343) --根據OBJID找到表名
1.DatabaseName 同於你要監測的數據庫名(不過這個好像不起作用,我的電腦上設置無效)
2.DatabaseID 同於你要檢測的數據庫的dbid,可以用 selectdb_id(N‘你要監測的庫名‘)得到dbid
3.ObjectName 同於你要監測的對象名,例如表名,視圖名等
4.ObjectID 同於你要監測的對象的id,可以用 select object_id(N‘你要監測的對象名‘)得到id
5.Error 同於錯誤,如果經常出現某個編號的錯誤,則針對此錯誤號
6.Seccess 同於0,失敗,1,成功,如果是排錯,就過濾掉成功的處理
select db_id(N‘ChinaHNDB_2013‘) --得到dbid select object_name(1813581499)
//*****************以下為SQL進行跟蹤,並得到跟蹤日誌,再結合SQL Server Profiler 分析 *******************************
declare @rc int
declare @TraceID int
declare @FileName sysname
declare @maxfilesize bigint
set @maxfilesize = 5
SELECT @FileName = ‘E:\lock2‘
-- 初始化跟蹤
exec @rc = sp_trace_create @TraceID output, 0, @FileName, @maxfilesize, NULL
--此處的e:/dblog/deadlockdetect是文件名(可自行修改),SQL會自動在後面加上.trc的擴展名
if (@rc != 0) goto error
-- 設置跟蹤事件
declare @on bit
set @on = 1
--下述語句中的148指的是locks:deadlock graph事件(參見sys.trace_events),12指的是spid列(參見sys.trace_columns)
exec sp_trace_setevent @TraceID, 148, 12, @on
exec sp_trace_setevent @TraceID, 148, 11, @on
exec sp_trace_setevent @TraceID, 148, 4, @on
exec sp_trace_setevent @TraceID, 148, 14, @on
exec sp_trace_setevent @TraceID, 148, 26, @on
exec sp_trace_setevent @TraceID, 148, 64, @on
exec sp_trace_setevent @TraceID, 148, 1, @on
-- 啟動跟蹤
exec sp_trace_setstatus @TraceID, 1
-- 記錄下跟蹤ID,以備後面使用
select TraceID = @TraceID
goto finish
error:
select [email protected]
finish:
go
exec sp_trace_setstatus 2, 0
exec sp_trace_setstatus 2, 2
select * from fn_trace_gettable(‘E:\lock2.trc‘,1)
/*
如果要暫停上面的服務器端跟蹤,可運行下面的語句:
exec sp_trace_setstatus 3, 0 --第一個參數表示TraceID,即步驟1中的輸出參數。第二個參數表示將狀態改為0,即暫停
如果要停止上面的服務器端跟蹤,可運行下面的語句:
exec sp_trace_setstatus 3, 2 --第一個參數表示TraceID,即步驟1中的輸出參數。第二個參數表示將狀態改為2,即停止
對於上面生成的跟蹤文件(e:/DbLog/deadlockdetect.trc),可通過兩種方法查看:
1.
select * from fn_trace_gettable(‘e:/DbLog/deadlockdetect.trc‘,1)
結果中的TextData列即以XML的形式返回死鎖的詳細信息。
2.
在SQL Server Profiler中打開。
依次 進入Profiler -> 打開跟蹤文件 ->選擇e:/DbLog/deadlockdetect.trc,就可以看到以圖形形式展現的死鎖信息了。
//*****************************************************************************************************
方法二: 用SQL Server Profiler分析死鎖(重點推薦,2014-4-3編輯)
1. 打開 SQL Server Management Studio >>工具 >> SQL Server Profiler
2.創建一個新的跟蹤
3.在事件選擇頁中,先勾選顯示所有事件,再選擇“死鎖圖形”事件、 “鎖定:死鎖”和“鎖定:死鎖鏈” (Deadlock graph,Lock:Deadlock;Lock:Deadlock Chain )如下圖所示:
,最後 取消其它默認事件選項((Deadlock graph,Lock:Deadlock;Lock:Deadlock Chain 以外事件) ,並運行。
4. 跟蹤一段時間,事務執行中止結束,選擇Deadlock graph,我們可以直觀查看到事務之間發生死鎖的原因:
上圖的橢圓形有一個叉,表示事務被SQL Server選擇為死鎖犧牲品,如果我們把鼠標指針移動到該叉橢圓中會出現一個提示。被鎖定Object 為Proc存儲過程(可以根據ID ,select object_id(N‘ID)
二個矩形框稱為資源節點,它們代表的數據庫對象,如表,行或索引。
由於事務A和B在擁有各自資源時試圖獲得對方資源的一個獨占鎖,使得進程相互等待對方釋放資源從而導致死鎖。
解決死鎖
這裏有幾個方法可以幫助我們解決死鎖問題。
優化查詢
我們在寫查詢語句時,要考慮一下查詢是否Join了沒有必要的表?是否返回數據太多(太多的列或行)?查詢是否執行表掃描?是否能通過調整查詢次序來避免死鎖?是否應該使用Join的地方使用了Left Join?Not In語句是否考慮周到?
我們在寫查詢語句可以根據以上準則來考慮查詢是否應該做出優化。
慎用With(NoLock)
默認情況下SELECT語句會對查詢到的資源加S鎖(共享鎖),由於S鎖與X鎖(排他鎖)不兼容,在加上With(NoLock)後,SELECT不對查詢到的資源加鎖(或者加Sch-S鎖,Sch-S鎖可以與任何鎖兼容);從而使得查詢語句可以更好和其他語句並發執行,適用於表數據更新不頻繁的情況。
也許有些人會提出質疑With(NoLock),可能會導致臟讀,首先我們要考慮查詢的表是否頻繁進行更新操作,而且是否要讀回來的數據會被修改,所以衡量是否使用With(NoLock)還是要根據具體實際出發。
優化索引
是否有任何缺失或多余的索引?是否有任何重復的索引?
處理死鎖
我們不能時刻都觀察死鎖的發生,但我們可以通過日誌來記錄系統發生的死鎖,我們可以把系統的死鎖錯誤寫入到表中,從而方便分析死鎖原因。
緩存
也許我們正在執行許多相同的查詢非常頻繁,如果我們把這些頻繁的操作都放到Cache中,執行查詢的次數將減少發生死鎖的機會。我們可以在數據庫的臨時表或表,或內存,或磁盤上應用Cache,或是磁盤文件。
SQL:查找被鎖的表,以及鎖表的SQL語句(重點推薦)