怎麼捕獲和記錄SQL Server中發生的死鎖

2021-06-20 13:37:18 字數 4269 閱讀 3798

我們知道,可以使用sql server自帶的profiler工具來跟蹤死鎖資訊。但這種方式有乙個很大的敝端,就是消耗很大。據國外某大神測試,profiler甚至可以佔到伺服器總頻寬的35%,所以,在乙個繁忙的系統中,使用profiler顯然不是乙個好主意,下面我介紹兩種消耗比較少的方法。其中第二種的消耗最小,在最繁忙的系統中也可使用。第一種最為靈活,可滿足多種應用。

方法一:利用sql server**(alert+job)

具體步驟如下:

1.首先使用下面的命令,將有關的跟蹤標誌啟用。

[c-sharp]view plain

copy

dbcc traceon (3605,1204,1222,-1)  

說明:3605 將dbcc的結果輸出到錯誤日誌。

1204 返回參與死鎖的鎖的資源和型別,以及受影響的當前命令。

1222 返回參與死鎖的鎖的資源和型別,以及使用了不符合任何 xsd 架構的 xml 格式的受影響的當前命令(比1204更進一步,sql 2005及以上可用)。

-1 以全域性方式開啟指定的跟蹤標記。

以上跟蹤標誌作用域都是全域性,即在sql server執行過程中,會一直發揮作用,直到sql server重啟。

如果要確保sql server在重啟後自動開啟這些標誌,可以在sql server服務啟動選項中,使用 /t 啟動選項指定跟蹤標誌在啟動期間設定為開。(位於sql server配置管理器->sql server服務->sql server->屬性->高階->啟動引數)

在執行上面的語句後,當sql server中發生死鎖時,已經可以在錯誤日誌中看到了,但還不夠直觀(和其它資訊混在一起)。(ssms -> sql server例項 -> 管理 -> sql server日誌)

2.建表,存放死鎖記錄

[c-sharp]view plain

copy

use [cole] --cole是我的示例資料庫,你可以根據實際情況修改。  

go  

create table deadlocklog (  

id int

identity (1, 1) not null,   

logdate datetime,   

processinfo varchar(10),   

errortext varchar(max)  

)  go  

3.建立job

新建乙個job(假設名稱為deadlockjob),在"步驟"中新建一步驟,隨便寫乙個步驟名稱,資料庫為"cole"(見2.建表),在"命令"欄中輸入以下語句:

[c-sharp]view plain

copy

--新建臨時表  

if object_id('tempdb.dbo.#errorlog'

) is not null  

drop table #errorlog  

create table #errorlog (id int

identity (1, 1) not null, a datetime, b varchar(10), c varchar(max))  

--將當前日誌記錄插入臨時表  

insert into #errorlog exec master.dbo.sp_readerrorlog  

--將死鎖資訊插入使用者表  

insert deadlocklog  

select a, b, c   

from #errorlog   

where id >= (select max(id) from #errorlog where c like '%deadlock encountered%'

)  drop table #errorlog  

4.新建警報

在"新建警報"窗體的"常規"選項卡中,進行以下設定:

名稱:可根據實際自行命名,這裡我用deadlockalert

型別:選擇"sql server效能條件警報"

物件:sqlserver:locks

計數器:number of deadlocks/sec

例項:_total

計數器滿足以下條件時觸發警報:高於

值:0設定完成後,應該如下圖所示:

在"響應"選項卡中,選中"執行作業",並選擇步驟3中我們新建的作業(即deadlockjob)

到這裡為止,我們已經完成了全部步驟,以後,你就可以隨時查詢deadlocklog表,來顯示死鎖資訊了。

方法二:利用伺服器端跟蹤。

具體實現步驟如下:

1.編寫如下指令碼,並執行

[c-sharp]view plain

copy

-- 定義引數  

declare @rc int

declare @traceid int

declare @maxfilesize bigint  

set@maxfilesize = 5   

-- 初始化跟蹤  

exec @rc = sp_trace_create @traceid output, 0, n'e:/dblog/deadlockdetect'

, @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 errorcode=@rc  

finish:   

go  

執行上述語句後,每當sql server中發生死鎖事件,都會自動往檔案e:/dblog/deadlockdetect.trc中插入一條記錄。

2.暫停和停止伺服器端跟蹤

如果要暫停上面的伺服器端跟蹤,可執行下面的語句:

exec sp_trace_setstatus 1, 0 --第乙個引數表示traceid,即步驟1中的輸出引數。第二個引數表示將狀態改為0,即暫停

如果要停止上面的伺服器端跟蹤,可執行下面的語句:

exec sp_trace_setstatus 1, 2 --第乙個引數表示traceid,即步驟1中的輸出引數。第二個引數表示將狀態改為2,即停止

3.檢視跟蹤檔案內容

對於上面生成的跟蹤檔案(e:/dblog/deadlockdetect.trc),可通過兩種方法檢視:

1).執行t-sql命令

[c-sharp]view plain

copy

select * from fn_trace_gettable(

'e:/dblog/deadlockdetect.trc'

,1)  

結果中的textdata列即以xml的形式返回死鎖的詳細資訊。

2).在sql server profiler中開啟。

依次 進入profiler -> 開啟跟蹤檔案 ->選擇e:/dblog/deadlockdetect.trc,就可以看到以圖形形式展現的死鎖資訊了。

記錄 輸入捕獲

捕獲輸入訊號脈衝的寬度。捕獲的概念是,捕獲邊沿訊號,同時將定時器的計數值儲存下牢。通過檢測輸入通道 timx chx 上的邊沿訊號,在邊沿訊號發生跳變 上公升沿 下降沿 的時候,將當前定時器的值 timx cnt 存入對應的捕獲 比較暫存器 timx ccrx 中,完成一次捕獲。定時器的輸入通道,就...

記錄 事件冒泡和事件捕獲

1 概念理解 所有瀏覽器中,都支援事件冒泡,即事件由子元素向祖先元素傳播的,就像氣泡從水底向水面上浮一樣。把事件捕獲和冒泡的過程統稱為事件的傳播。而在像firefox,chrome,safari這類所謂的標準瀏覽器中,事件傳播還有個階段,那就是捕獲階段,先發生捕獲的過程,再發生冒泡的過程。這個很少有...

Python 怎麼捕獲警告?(注意 不是捕獲異常)

你是不是經常在使用一些系統庫或者第三方模組的時候,會出現一些既不是異常也不是錯誤的警告資訊?這些警告資訊,有時候非常多,對於新手容易造成一些誤判,以為是程式出錯了。實則不然,異常和錯誤,都是程式出現了一些問題,但是警告不同,他的緊急程度非常之低,以致於大多數的警告都是可以直接忽略的。如果不想顯示這些...