2013-03-17 71 views
1

我已经阅读了大量有关Internet上死锁的信息,以确保我没有问一个愚蠢的问题。下表中,发生死锁的位置用作订单队列。没有记录实际上被删除,只有它们的状态改变,即处理,取消,完成。 我在此表上观察SELECTs with UPDLOCK上的神秘死锁。我看到的关于SELECT的唯一特性是有一个内部的SELECT without UPDLOCK,但那不应该。该表已启用行锁定。这些SELECTS由独立的作业调度程序并行运行。这种SELECT的含义是,它检索具有一个或多个指定状态(上述“处理,取消,完成”)的第一个(最早)订单。具有最小ID的订单(最小ID是手动选择的,在下面的查询中是6850000)被认为是“第一”订单。这是出于性能原因而完成的。下面是一个实际的SELECT:非常神秘的死锁

select * from TORDERSUMMARY with (updlock, rowlock) 
where ID in 
(select min(ID) from TORDERSUMMARY 
where ID > 6850000 and (ORDERSTATUS in ('INITIATED')) 
and (ORDERDISPATCHSTATUS in (0 , 2 , 4)) and (ORDERGROUPID is null)) 

在表中的主键ID上定义了聚簇索引。如SQL Server Management Studio 2008所给出的,这些查询的估计和实际执行计划是集群索引查找。表中有许多非聚集索引,我希望NC索引操作在聚集索引操作时发生死锁(我详细阅读了网上的许多这种情况),但由于只有聚集索引以最好的方式使用(索引搜索),原因似乎并不在于此。

内部SELECT没有UPDLOCK,ROWLOCK提示,所以没有多个记录被锁定。我无法想象任何两个这样的选择都会陷入僵局的情景。当然,UPDLOCK提示是因为代码随后尝试更新订单状态(将其标记为已处理等)。

这是一个来自SQL Server Management Studio 2008的死锁XDL文件 - http://pastebin.com/ugCUbn80。服务器本身是9.0.4035。 SQL查询很长,所以由于某些原因,它们在XDL文件中被截断,但是SELECTs肯定是上述类型的,因为我已经用这些SELECT完成了对服务器的手动压力测试,并且看起来随机地发生了死锁办法。

回答

0

规则1:不要在您的仿真钥匙上建立聚簇索引;在您的自然键上构建聚集索引并为您的人造键构建非聚集索引。

+0

从技术上讲,这将是一个意见不是一个规则:)。在自然键上构建聚簇索引有一些非常好的理由,但是它们也是你为什么要在人工键上构建它的一些同样好的理由。 – 2013-03-18 12:05:41