2017-03-20 2 views
1

Ich habe einen täglichen Job, der eine Anweisung dbcc checkdbb ohne zusätzliche Parameter in jeder der Systemdatenbanken ausführt. Dieser Job wird außerhalb der Stoßzeiten ausgeführt und dauert in der Regel 5 Sekunden oder weniger.Warum verursachen dbcc checkdb in Systemdatenbanken und sp_executesql in einer Benutzerdatenbank einen Deadlock?

Der letzte Lauf dauerte jedoch nur 1 Sekunde und scheiterte an einem Deadlock. Ich habe eine Warnung erhalten, die mir eine XML-Grafik des Deadlocks speichert, die ich für detailliertere Informationen einschließe.

Meine Hauptfragen sind: Warum tritt solch ein Deadlock tatsächlich auf und ist es vermeidbar?

<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> 

Lösung Ich habe implementiert für TempDB Benutzertransaktionen über Täglich checkdb priortize:

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

Im Anschluss an die Antwort von @TheGameiswar posten wir auch die Lösung, die ich implementiert habe. Ich überprüfe immer noch tempdb, aber jetzt habe ich die Prozedur Ich verwende eine niedrigere Deadlock-Priorität. Die Idee ist, dass Benutzertransaktionen über eine tägliche Systemprüfung, genauer gesagt die von tempdb, priorisiert werden sollten. Da ein Deadlock-Szenario nur sporadisch auftritt, scheint es eine praktikable Alternative zu sein. –

Antwort

0

Warum dbcc checkdb auf Systemdatenbanken und Sp_executesql auf einer Benutzerdatenbank führen zu einem Deadlock tun?

DBCC CHECKDB erworben Intent Exclusive Sperre auf tempdb.sys.sysrowsets und ist für eine sharedlock auf tempdb.sys.sysrscols warten ..

Ihren Benutzer proc, auch auf tempdb.sys.sysrscols TEMPDB resources.This Benutzer proc erworben IX-Sperre zugreift und ist für eine gemeinsame Sperre auf tempdb.sys.sysrowsets warten ..

So Deadlock aufgetreten ist, und dies ist ein einfacher Fall von Deadlock

Normalerweise DBCC CheckDB Snapshot der Datenbank vor der Analyse nimmt und es funktioniert auf diesem Snapshot zu vermeiden, Sperren, Blockieren ..

In diesem Fall as per this post ..Snapshot ist nicht möglich mit TEMPDB und so in Ihrem Fall gibt es inkompatible Sperren von beiden Transaktionen erworben, die der Grund für den Deadlock ist du sahst.

+0

Danke für die Antwort @TheGameiswar. Es macht durchaus Sinn, dass Tempdb in der Mitte dieses Deadlocks war, wie du gesagt hast. Ich war unter der Annahme, dass die dbcc Checkdb-Anweisung einen Snapshot erstellen würde, aber die Tempdb-Ausnahme übersehen. –

Verwandte Themen