【发布时间】:2014-09-04 09:29:24
【问题描述】:
我在 SQL Server (Azure SQL) 中有一个表:
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 锁定 IX_PriorityAndDate 索引(U 锁定)。
- 会话 2 锁定 PK_Commands 索引(X 锁定)。
- 会话 1 阻塞等待 PK_Commands(获取 U 锁)。
- 会话 2 在等待 IX_PriorityAndDate 时阻塞(获取 X 锁)。
如何解决这个死锁?
【问题讨论】:
-
同一个命令同时被更新和删除不是逻辑bug吗?或者 IX_PriorityAndDate 上的索引访问是否读取多行?在那种情况下,为什么会有一个 UPDLOCK 提示?删除它并使用 READ COMMITTED 或快照隔离。
-
这不是逻辑错误,这些查询是在不同的上下文中针对不同的行执行的。无论有或没有 WITH(UPDLOCK) 提示,都会发生相同的死锁。我会删除它以使问题更清楚。
-
这些语句在什么隔离级别下运行?
-
检查执行计划以确保索引按预期使用(即没有扫描/排序)。
-
@usr,它已提交读。
标签: sql sql-server azure-sql-database deadlock