2017-03-20 36 views
1

我有一個日常工作,在每個系統數據庫上運行沒有附加參數的dbcc checkdb語句。此作業在非高峯時段運行,通常需要5秒或更少時間才能運行。爲什麼系統數據庫上的dbcc checkdb和用戶數據庫上的sp_executesql導致死鎖?

但是最後一次運行只花了1秒鐘,並且因爲死鎖而失敗。我有一個警告,爲我節省了一個死鎖的xml圖,我將其中包含更多詳細信息。

我的主要問題是:爲什麼會發生這樣的死鎖並且可以避免?

<TextData> 
     <deadlock-list> 
    <deadlock victim="process290fd861088"> 
     <process-list> 
     <process id="process290fd861088" taskpriority="0" logused="0" waitresource="OBJECT: 2:5:0 " ownerId="1250115008" transactionname="CheckDb" lasttranstarted="2017-03-20T01:00:01.427" XDES="0x2b277040bd8" lockMode="S" schedulerid="7" kpid="12760" status="suspended" spid="78" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2017-03-20T01:00:00.060" lastbatchcompleted="2017-03-20T01:00:00.060" lastattention="1900-01-01T00:00:00.060" clientapp="SQLAgent - TSQL JobStep (Job 0xB425122DD6C28D4BBE42D7F0AF76FC40 : Step 1)" hostname="0000-DB-0000" hostpid="8040" loginname="0000\0000" isolationlevel="read committed (2)" xactid="1250115008" currentdb="2" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056"> 
     <executionStack> 
     <frame procname="0000_Local.server.CheckSystemDatabases" line="19" stmtstart="740" stmtend="776" sqlhandle="0x030006006a934a11b3ebcd0023a7000001000000000000000000000000000000000000000000000000000000"> 
    dbcc checkdb(@dbId  </frame> 
     <frame procname="adhoc" line="1" stmtend="70" sqlhandle="0x010006006688101b405fcfceb602000000000000000000000000000000000000000000000000000000000000"> 
    exec [server].[CheckSystemDatabases  </frame> 
     </executionStack> 
     <inputbuf> 
    exec [server].[CheckSystemDatabases]; </inputbuf> 
     </process> 
     <process id="process2b59a715468" taskpriority="0" logused="952" waitresource="OBJECT: 2:3:0 " ownerId="1250114957" transactionname="droptemp" lasttranstarted="2017-03-20T01:00:01.423" XDES="0x29b8755ce58" lockMode="IX" schedulerid="8" kpid="9440" status="suspended" spid="67" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2017-03-20T01:00:01.410" lastbatchcompleted="2017-03-20T01:00:01.410" lastattention="1900-01-01T00:00:00.410" clientapp="0000-API-0000" hostname="0000-0000-WEB-0000" hostpid="42180" loginname="0000\0000" isolationlevel="read committed (2)" xactid="0" currentdb="9" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056"> 
     <executionStack> 
     <frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000"> 
    sp_executesql  </frame> 
     <frame procname="0000.dbo.SomeProcName" line="93" stmtstart="8320" stmtend="8496" sqlhandle="0x030009002ac137082fa8b20029a7000001000000000000000000000000000000000000000000000000000000"> 
    exec sp_executesql @selectSql, N'@rowcount int output', @rowcount = @TotalRowCount outpu  </frame> 
     </executionStack> 
     <inputbuf> 
    Proc [Database Id = 9 Object Id = 137871658] </inputbuf> 
     </process> 
     </process-list> 
     <resource-list> 
     <objectlock lockPartition="0" objid="5" subresource="FULL" dbid="2" objectname="tempdb.sys.sysrowsets" id="lock2b4103b8380" mode="IX" associatedObjectId="5"> 
     <owner-list> 
     <owner id="process2b59a715468" mode="IX" /> 
     </owner-list> 
     <waiter-list> 
     <waiter id="process290fd861088" mode="S" requestType="wait" /> 
     </waiter-list> 
     </objectlock> 
     <objectlock lockPartition="0" objid="3" subresource="FULL" dbid="2" objectname="tempdb.sys.sysrscols" id="lock291f3d8a900" mode="S" associatedObjectId="3"> 
     <owner-list> 
     <owner id="process290fd861088" mode="S" /> 
     </owner-list> 
     <waiter-list> 
     <waiter id="process2b59a715468" mode="IX" requestType="wait" /> 
     </waiter-list> 
     </objectlock> 
     </resource-list> 
    </deadlock> 
    </deadlock-list></TextData> 

解決方案,我已經實現了對檢測優先級超過每日CHECKDB用戶交易爲tempdb:

set nocount on; 
set deadlock_priority low; 
declare @dbId int; 
declare loopCheckDB cursor fast_forward 
for select [d].[database_id] from [sys].[databases] as [d] where [d].[database_id] < 5 
order by [d].[name] 
open [loopCheckDB] 
fetch next from [loopCheckDB] into @dbId; 
while @@FETCH_STATUS = 0 
begin dbcc checkdb(@dbId); 
fetch next from [loopCheckDB] into @dbId; 
end 
close [loopCheckDB]; 
deallocate [loopCheckDB]; 
+0

根據@TheGameiswar給出的答案,我也發佈了我已經實現的解決方案。 我仍在檢查tempdb,但現在已經給我使用較低的死鎖優先級的過程。這個想法是用戶事務應該優先於每日系統檢查,更具體地說是tempdb。看到像這樣的死鎖情景,只是偶爾發生,這似乎是一個可行的選擇。 –

回答

0

爲什麼對系統數據庫和sp_executesql的用戶數據庫上DBCC CHECKDB導致死鎖?

DBCC CHECKDB獲取上tempdb.sys.sysrowsets意向排他鎖,並正在等待上tempdb.sys.sysrscols一個sharedlock ..

用戶PROC,也訪問TEMPDB resources.This用戶PROC上tempdb.sys.sysrscols獲取IX鎖並且正在等待上tempdb.sys.sysrowsets共享鎖..

因此發生死鎖,這是僵局的一個簡單的例子

通常情況下,DBCC CHECKDB使數據庫的快照分析之前,它的工作原理在這個快照,以避免鎖定,阻止..

在這種情況下,as per this post ..快照是不可能與TEMPDB,所以在你的情況下,有兩個事務獲得不兼容的鎖,這是死鎖的原因你看到了。

+0

感謝@TheGameiswar的回答。 tempdb處於這個僵局的中間,就像你說的那樣,這是非常有意義的。 我假設dbcc checkdb語句會創建快照,但忽略了tempdb異常。 –

相關問題