1,process-list顯示兩個進程之間存在死鎖:process60fb88和process 11902 c8。
2.vistim-list顯示進程60fb88被選為受害者。
2.下面的資源列表顯示了兩個進程爭奪並導致死鎖的資源。
[html]查看純文本
& lt死鎖& gt
& lt受害者名單& gt
& ltvictim process id = " process 60 FB 88 "/& gt;
& lt/受害者列表& gt
& lt進程列表& gt
& ltprocess id = " process 60 FB 88 " task priority = " 0 " logused = " 0 " wait resource = " KEY:9:72057597664231424(7506 ff 9 b 7 b 0d)" wait time = " 4376 " ownerId = " 2656658629 " transaction name = " SELECT " last trans started = " 2014-04-09t 23:065433Net SqlClient數據提供程序" hostname = " bodcprodvsql 128 " hostpid = " 10088 " loginname = " PROD \ s-propdata " isolation level = " read committed(2)" xactid = " 2656658629 " current db = " 9 " lock time out = " 4294967295 " client option 1 = " 67108866
& ltexecutionStack & gt
& ltframe proc name = " " line = " 9 " stmt start = " 336 " STM tend = " 874 " SQL handle = " 0x 030009003 d00 da 3a 6087 c 0182 a 200000010000000000 "/>
& ltframe proc name = " " line = " 20 " stmt start = " 1022 " STM tend = " 1206 " SQL handle = " 0x 03000900941f 284 ed 5929 e 00 ABA 2000000010000000000 "/>
& ltframe proc name = " " line = " 9 " stmt start = " 464 " STM tend = " 642 " SQL handle = " 0x 03000 a 006502 e 0715 df 5 af 00 ABA 200000010000000000 "/>
& ltframe proc name = " " line = " 4 " stmt start = " 224 " STM tend = " 420 " SQL handle = " 0x 01000 a 00 b 6 FCA 934509742900 b 00000000000000000 "/>
& lt/execution stack & gt;
& ltinputbuf & gt
DECLARE @logText NVARCHAR(MAX)
EXEC integrated service _ ProcessLatestCommand @ log text OUTPUT
選擇@ logText & lt/input buf & gt;
& lt/process & gt;
& ltprocess id = " process 11902 c8 " task priority = " 0 " logused = " 232 " wait resource = " KEY:9:72057596808265728(ed 2e 944 bef F9)" wait time = " 4379 " ownerId = " 2656658630 " transaction name = " UPDATE " lastranstarted = " 2014-04-09t 2Net SqlClient數據提供程序" hostname = " bodcprodvsql 128 " hostpid = " 1 0088 " loginname = " PROD \ s-propdata " isolation level = " read committed(2)" xactid = " 2656658630 " current db = " 9 " lockTimeout = " 4294967295 " client option 1 = " 67108866
& ltexecutionStack & gt
& ltframe proc name = " " line = " 22 " stmt start = " 1230 " STM tend = " 1496 " SQL handle = " 0x 030009003d 00 da 3a 3fa 6087 c 0182 a 2000000010000000000 "/>
& ltframe proc name = " " line = " 20 " stmt start = " 1022 " STM tend = " 1206 " SQL handle = " 0x 03000900941f 284 ed 5929 e 00 ABA 2000000010000000000 "/>
& ltframe proc name = " " line = " 9 " stmt start = " 464 " STM tend = " 642 " SQL handle = " 0x 03000 a 006502 e 0715 df 5 af 00 ABA 200000010000000000 "/>
& ltframe proc name = " " line = " 4 " stmt start = " 224 " STM tend = " 420 " SQL handle = " 0x 01000 a 00 b 6 FCA 934509742900 b 00000000000000000 "/>
& lt/execution stack & gt;
& ltinputbuf & gt
DECLARE @logText NVARCHAR(MAX)
EXEC integrated service _ ProcessLatestCommand @ log text OUTPUT
選擇@ logText & lt/input buf & gt;
& lt/process & gt;
& lt/process-list & gt;
& lt資源列表& gt
& ltkey lock hob tid = " 72057597664231424 " dbid = " 9 " object name = " " index name = " " id = " lockc 99859500 " mode = " X " associated objectid = " 72057597664231424 " >
& lt所有者列表& gt
& ltowner id = " process 11902 c8 " mode = " X "/& gt;
& lt/owner-list & gt;
& lt服務員名單& gt
& ltwaiter id = " process 60 FB 88 " mode = " S " request type = " wait "/& gt;
& lt/waiter-list >
& lt/key lock & gt;
& ltkey lock hob tid = " 72057596808265728 " dbid = " 9 " object name = " " index name = " " id = " lock 2f 4de 2d 00 " mode = " S " associated objectid = " 72057596808265728 " >;
& lt所有者列表& gt
& ltowner id = " process 60 FB 88 " mode = " S "/& gt。
& lt/owner-list & gt;
& lt服務員名單& gt
& ltwaiter id = " process 11902 c8 " mode = " X " request type = " wait "/& gt;
& lt/waiter-list >
& lt/key lock & gt;
& lt/resource-list & gt;
& lt/deadlock & gt;
以下是詳細分析。
1,受害者列表沒什麽可分析的。
2.進程列表中每個進程的詳細信息非常重要。
wait resource = " KEY:9:72057597664231424(7506 ff 9 b 7 b 0d)"
當前進程正在等待的資源。通常我們可以在資源列表中看到相同的信息。使用以下sql查詢,等待的資源是什麽:
下面用的Hobtid是heap或者b樹id的縮寫。有關詳細信息,請參見sys.partotions的說明。
[sql]查看普通副本
選擇o.name,i.name
從系統分區p
在p.object_id = o.object_id上聯接sys.objects o
在p.object_id = i.object_id上聯接sys.indexes i
並且p.index_id = i.index_id
其中p.hobt_id = 72057597664231
名字名字
-
匹配服務主鍵_匹配者標識
從結果中我們可以知道,等待的資源是壹個表MatchService的主鍵PK_Matcher_ID。再看另壹個進程的waitresource,可以知道等待資源是同壹個表的另壹個索引。到目前為止,我們已經找到了直接導致死鎖的資源。
同時可以看到兩個進程,壹個是x鎖,壹個是s鎖。因此,可以判斷表上的修改語句和查詢語句之間發生了死鎖。
另外,在上面的例子中可以清楚地看到keylock導致的死鎖,所以對應的對象(sys。partitions包含所有分區中每個分區的壹行)可以通過查詢分區來找到。
數據庫中的表和大多數類型的索引。)。但是有時候其他類型的資源也會死鎖,比如pagelock,wait resource = " page:9:1:28440841 "。9是dbid1是fileid28440841是pageid。在這種情況下,使用以下語句查詢相應的資源:
[sql]查看普通副本
DBCC·特雷西恩(3604)
去
DBCC頁(9,1,28440841)
去
DBCC溯源(3604)
去
從返回的元數據中找到對應的objectId:objectId。
3.看看進程中的inputbuf。該標簽表示進程正在運行的語句,因此對於定位死鎖非常重要。但是這裏有壹個問題,比如
在上面的例子中,inputbuf是壹個存儲過程,其中嵌套了很多其他存儲過程,但是inputbuf是用戶直接發送的sql,我們需要找出哪個直接導致死亡。
鎖定語句並進行優化,從而解決或減少死鎖。從此我們有了導致死鎖的語句被inputbuf中的語句調用的信息,導致死鎖的語句壹定是表。
MatchService的修改語句。如果存儲過程很簡單,DBA就能夠找到直接導致死鎖的sql,分析過程到此結束。如果存儲過程很復雜,那麽
需要進壹步分析。
4.現在讓我們仔細看看標記executionStack。ExecutionStack顯示了發生死鎖時inputbuf進行的壹系列調用。
sql .上面的例子中有4個sql。同時,仔細觀察上面的例子可以發現,兩個進程的executionStack是完全壹樣的,所以考察壹個就夠了。此外,
如果procname不為空,則直接獲得sql,但上面示例中的標記為空。
此後,我們希望在executionStack中顯示所有sql。使用下面的sql找出內存中對應sqlhandle的sql。需要註意的是
但是如果死鎖已經過去了壹段時間,sqlhandle可能已經從內存中清除了,此時無法查找。而sqlhandle是
Varbinaryd,所以查詢時不能用引號。
還有壹個有趣的點:和其他編程語言壹樣,棧頂的是最直接的錯誤,後面的錯誤都是錯誤下壹級的錯誤(這個解釋可能有點
亂,寫過代碼的同學都能理解。所以在存儲過程調用前面提到的存儲過程的情況下,executionStack中第壹項是直接導致死鎖的sql,第二項是調試。
加上這個sql的sql,以此類推,最後壹個理論上是inputbuf中的sql。
[sql]查看普通副本
選擇sql_handle作為句柄,
SUBSTRING(st.text,(QS . statement _ start _ offset/2)+1,
((CASE qs.statement_end_offset
當-1時,則DATALENGTH(st.text)
否則qs.statement_end_offset
END-QS . statement _ start _ offset)/2)+1)作為文本
來自sys.dm_exec_query_stats AS qs
交叉應用sys . DM _ exec _ SQL _ text(QS . SQL _ handle)作為st
其中SQL _ handle = 0x 030009003 d00 da 3 fa 6087 c 0182 a 20000010000000000
按sql_handle排序
- -
0x 030009003d 00 da 3a fa 6087 c 0182 a 20000001000000000000 select
TOP 1 @matcherQueueID = lhs。匹配器服務_匹配器隊列_ID,
@ Root Operation UID = Root _ Operation _ UID FROM
MatcherService_MatcherQueue lhs其中lhs。處理狀態
= '匹配'或lhs。Processing_State = 'MATCHED '排序依據
上次執行日期
0x 030009003d 00 da 3 fa 6087 c 0182 a 20000001000000000000
從GEDemo.dbo.OperationLog中選擇Top 1 @ ticket ID = operation log _ ID
其中@ Root Operation UID = Root _ Operation _ UID,Status = 0
按工序排序Log_ID ASC
0x 030009003d 00 da 3 fa 6087 c 0182 a 20000001000000000000
UPDATE matcher service _ matcher queue SET Last _ Execution _ Date =
GETDATE(),其中matcher service _ matcher queue _ ID = @ matcher queue ID
註意,似乎壹個sql_handle有三個語句,因為這三個sql屬於同壹個存儲過程。
如果壹個sql_handle包含許多語句,比如壹個長存儲過程,那麽我們還可以使用壹個強大的信息:在
線條
標簽。該語句顯示了哪個sql直接導致了死鎖。如果壹個語句包含許多表,則需要結合死鎖資源來確定哪個表或。
索引的數據被死鎖。