각 시스템 데이터베이스에 추가 매개 변수없이 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를 통해 사용자 트랜잭션을 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];
@ TheGameiswar가 제공 한 답변에 이어 다음과 같이 구현 한 솔루션도 게시하고 있습니다. 여전히 tempdb를 확인하고 있지만 이제 교착 상태 우선 순위가 낮은 프로 시저를 제공합니다. 사용자 트랜잭션은 일별 시스템 검사, 특히 tempdb의 우선 순위에 따라 우선 순위를 지정해야한다는 아이디어가 있습니다. 이와 같은 교착 상태 시나리오가 산발적으로 발생하는 것만으로도 가능한 선택 인 것으로 보입니다. –