【发布时间】:2017-01-31 08:48:25
【问题描述】:
在检查下面的死锁图时,我发现一个SELECT 查询(仅在SP 内由第一个进程process569f048 执行的查询)和一个UPDATE 查询形成了死锁; SELECT 查询需要 IX 锁定。
在什么情况下SELECT 需要这种锁?我该怎么做才能避免死锁?
这里是SELECT 查询:
SELECT TOP (@p_takeCount)
t.Id
,s.Column2
,t.STATUS
,t.Column3
,t.Column4
FROM Table2 t WITH (INDEX (IX_Table2))
INNER JOIN Table1 s ON s.Id = t.ParentId
WHERE t.STATUS != 0
AND t.Column5 IS NULL
AND s.SomeId = @p_someId
AND s.Category = 2
ORDER BY t.id
计划如下:
这是UPDATE 查询:
update Table2
set [Status] = @0, Column5 = null, Column6 = @1
where ([Id] = @2)
计划如下:
这是死锁图:
<deadlock>
<victim-list>
<victimProcess id="process569f048" />
</victim-list>
<process-list>
<process id="process569f048" taskpriority="0" logused="0" waitresource="PAGE: 5:1:3017144" waittime="2867" ownerId="964271246" transactionname="SELECT" lasttranstarted="2017-01-29T10:10:49.643" XDES="0x800f9d20" lockMode="S" schedulerid="10" kpid="10108" status="suspended" spid="70" sbid="2" ecid="2" priority="0" trancount="0" lastbatchstarted="2017-01-29T10:10:49.643" lastbatchcompleted="2017-01-29T10:10:49.643" clientapp="EntityFramework" hostname="LOCALHOST" hostpid="4936" isolationlevel="read committed (2)" xactid="964271246" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="" line="17" stmtstart="1298" stmtend="1954" sqlhandle="0x03000500d21f5e3dd6d19700cca400000100000000000000" />
</executionStack>
<inputbuf />
</process>
<process id="process8ee3dc8" taskpriority="0" logused="17956" waitresource="PAGE: 5:1:3017343" waittime="2864" ownerId="964271345" transactionname="user_transaction" lasttranstarted="2017-01-29T10:10:49.667" XDES="0xafdbb03b0" lockMode="IX" schedulerid="17" kpid="9468" status="suspended" spid="61" sbid="2" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-01-29T10:10:49.703" lastbatchcompleted="2017-01-29T10:10:49.703" clientapp="EntityFramework" hostname="LOCALHOST" hostpid="20696" loginname="dbuser_d" isolationlevel="read committed (2)" xactid="964271345" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="" line="1" stmtstart="74" sqlhandle="0x02000000403aaa03bd8879de1c73d49641f1f81b6ca095af" />
<frame procname="" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000" />
</executionStack>
<inputbuf>
(@0 tinyint,@1 varchar(64),@2 bigint)update [dbo].[Table2]
set [Status] = @0, [Column5] = null, [Column6] = @1
where ([Id] = @2)
</inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="3017144" dbid="5" objectname="" id="lockc296c6380" mode="IX" associatedObjectId="72057594073317376">
<owner-list>
<owner id="process8ee3dc8" mode="IX" />
</owner-list>
<waiter-list>
<waiter id="process569f048" mode="S" requestType="wait" />
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="3017343" dbid="5" objectname="" id="lockd33965a80" mode="S" associatedObjectId="72057594073317376">
<owner-list>
<owner id="process569f048" mode="S" />
</owner-list>
<waiter-list>
<waiter id="process8ee3dc8" mode="IX" requestType="wait" />
</waiter-list>
</pagelock>
</resource-list>
</deadlock>
索引详情:
[PK_Table2] PRIMARY KEY CLUSTERED ([Id] ASC);
[IX_Table2]([Column5] ASC, [Status] ASC) INCLUDE ( [Id],[ParentId],[Column3],[Column4]) WHERE ([Column5] IS NULL);
ID 为 72057594073317376 (associatedObjectId) 的对象是:[IX_Table2]
【问题讨论】:
-
索引提示,真的吗?您正在使用哪些其他“自定义”?表上的索引是如何定义的?
-
选择从表过滤状态中获取
TOP x,而更新正在更新状态... -
@Shnugo 我明白这一点。但这不应该只是阻止一个交易吗?为什么会出现僵局?
-
这也类似于dba.stackexchange.com/questions/62947/… - 我认为这是关键,即使
SELECT只使用非聚集索引,它仍然需要锁定聚集索引以防止更新聚类键。关联的 object_id 72057594073317376 是聚集索引还是非聚集索引的 object_id?
标签: sql-server database sql-server-2008-r2 deadlock