2014-09-04 97 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)