2014-09-04 26 views
5

我在SQL服务器(SQL Azure中)的表:两个指数死锁

CREATE TABLE Commands 
(
    Id int NOT NULL PRIMARY KEY, 
    Body nvarchar(1000) NOT NULL, 
    Priority int NOT NULL, 
    DeliveryDate datetime NOT NULL, 
    VisibleFrom datetime NULL, 
) 

表中也有一个指标:

CREATE NONCLUSTERED INDEX IX_PriorityAndDate ON Commands (Priority DESC, DeliveryDate ASC) 

然后,我有两个会话。

会话1

WITH command AS 
(
    SELECT TOP(1) * 
    FROM Commands q 
    WHERE q.DeliveryDate <= @CurrentDate 
     AND (q.VisibleFrom IS NULL OR q.VisibleFrom <= @CurrentDate) 
    ORDER BY q.Priority DESC, q.DeliveryDate 
) 
UPDATE command SET command.VisibleFrom = DATEADD(SECOND, @LeaseTimeout, @CurrentDate) 
OUTPUT inserted.Id, 
     inserted.Body 

会话2

DELETE FROM Commands WHERE Id = @Id 

在某些情况下发生死锁:

  1. 会话1个锁IX_PriorityAndDate指数(U锁)。
  2. 会话2锁定PK_Commands索引(X锁定)。
  3. 会话1阻塞等待PK_Commands(获取U锁)。
  4. 会话2阻止等待IX_PriorityAndDate(获取X锁)。

如何解决这个死锁?

+0

不是吧同一个命令正在被更新和删除的逻辑错误?或者IX_PriorityAndDate上的索引访问是否读取多行?在那种情况下,为什么会有UPDLOCK提示?删除它并使用READ COMMITTED或快照隔离。 – usr 2014-09-04 09:37:58

+0

这不是一个逻辑错误,这些查询是针对不同的行在不同的上下文中执行的。有或没有WITH(UPDLOCK)提示时发生相同的死锁。我会删除它以使问题更清楚。 – alexey 2014-09-04 09:40:28

+0

这些语句在哪些隔离级别下运行? – usr 2014-09-04 09:58:22

回答

1

在我看来,你有钥匙查找僵局

尝试使用以下指标:

CREATE NONCLUSTERED INDEX IX_PriorityAndDate 
    ON Commands (Priority DESC, DeliveryDate ASC) INCLUDE(VisibleFrom) 

或尝试创建新的索引:

CREATE NONCLUSTERED INDEX IX_PriorityAndDate 
    ON Commands(DeliveryDate, VisibleFrom) INCLUDE(Priority)