Вам необходимо проверить предыдущие SQL-операторы в той же транзакции.
График взаимоблокировки просто показывает вам стек вызовов для операторов, выполняемых при возникновении взаимоблокировки. Заявления, которые фактически получили заблокированные ресурсы, могут отсутствовать. Это легко продемонстрировать следующим образом.
Соединение 1
CREATE TABLE T1
(
id INT PRIMARY KEY,
foo CHAR(100),
bar CHAR(100)
)
INSERT INTO T1
(id)
VALUES (1),
(2)
GO
BEGIN TRAN
UPDATE T1
SET foo = '123'
WHERE id = 1
WAITFOR DELAY '00:00:05'
GO
UPDATE T1
SET bar = 'dlock'
WHERE id = 2
ROLLBACK
DROP TABLE T1
Соединение 2 (выполняется быстро после соединения 1)
BEGIN TRAN
UPDATE T1
SET foo = '123'
WHERE id = 2
WAITFOR DELAY '00:00:05'
GO
UPDATE T1
SET bar = 'dlock'
WHERE id = 1
ROLLBACK
График тупиковой ситуации
<process-list>
<process
id="process520d1c8"
taskpriority="0"
logused="504"
waitresource="KEY: 1:72057594051100672 (010086470766)"
waittime="3666"
ownerId="10399789"
transactionname="user_transaction"
lasttranstarted="2011-10-30T13:45:29.030"
XDES="0x4eb5be8"
lockMode="X"
schedulerid="2"
kpid="8656"
status="suspended"
spid="59"
sbid="0"
ecid="0"
priority="0"
trancount="2"
lastbatchstarted="2011-10-30T13:45:34.047"
lastbatchcompleted="2011-10-30T13:45:34.043"
clientapp="Microsoft SQL Server Management Studio - Query"
hostname="MyPC"
hostpid="7544"
loginname="Me"
isolationlevel="read committed (2)"
xactid="10399789"
currentdb="1"
lockTimeout="4294967295"
clientoption1="671090784"
clientoption2="390200">
<executionStack>
<frame
procname="adhoc"
line="2"
stmtstart="58"
sqlhandle="0x02000000b24eb7001f552b64e5c2bf2ccb1f2acfda154410">
UPDATE [T1] set [bar] = @1 WHERE [id]=@2
</frame>
<frame
procname="adhoc"
line="2"
stmtstart="4"
stmtend="90"
sqlhandle="0x020000002688730e96c94af4582dfb097fa79a39ea620d63">
UPDATE T1 SET bar = 'dlock' where id=1
</frame>
</executionStack>
<inputbuf>
UPDATE T1 SET bar = 'dlock' where id=1
rollback
</inputbuf>
</process>
<process
id="process370d8718"
taskpriority="0"
logused="504"
waitresource="KEY: 1:72057594051100672 (020068e8b274)"
waittime="5579"
ownerId="10399738"
transactionname="user_transaction"
lasttranstarted="2011-10-30T13:45:27.040"
XDES="0x1ef7ac10"
lockMode="X"
schedulerid="1"
kpid="2060"
status="suspended"
spid="52"
sbid="0"
ecid="0"
priority="0"
trancount="2"
lastbatchstarted="2011-10-30T13:45:32.083"
lastbatchcompleted="2011-10-30T13:45:32.043"
clientapp="Microsoft SQL Server Management Studio - Query"
hostname="MyPC"
hostpid="7544"
loginname="Me"
isolationlevel="read committed (2)"
xactid="10399738"
currentdb="1"
lockTimeout="4294967295"
clientoption1="671098976"
clientoption2="390200">
<executionStack>
<frame
procname="adhoc"
line="3"
stmtstart="58"
sqlhandle="0x02000000b24eb7001f552b64e5c2bf2ccb1f2acfda154410">
UPDATE [T1] set [bar] = @1 WHERE [id]=@2
</frame>
<frame
procname="adhoc"
line="3"
stmtstart="8"
stmtend="94"
sqlhandle="0x020000004a869b267636c00306e481791dec78ade36b3f39">
UPDATE T1 SET bar = 'dlock' where id=2
</frame>
</executionStack>
<inputbuf>
UPDATE T1 SET bar = 'dlock' where id=2
ROLLBACK
DROP TABLE T1
</inputbuf>
</process>
</process-list>
Присвоения столбцу foo
, который получил блокировки в первую очередь, не отображаются.
(NB: без оператора GO
для разделения операторов на отдельные пакеты в этом случае вы бы увидели оператор, нарушающий работу, но в целом получение блокировки может происходить дальше по стеку вызовов, поэтому оператор, который фактически получил блокировки, все равно не будет не будет показано)