存储过程SQL Server 2005事务死锁问题

时间:2011-02-18 18:41:44

标签: sql sql-server-2005 stored-procedures

我在运行sql存储过程时遇到问题(MSSQL 2005)。这是它的代码:

CREATE PROCEDURE [GetItemColors]
    @FetchCount int
AS
BEGIN
SELECT 
    TOP (@FetchCount) item.Id as ItemId, item.Published as Published, attributeValue.String as Color
    FROM tblItem item, tblAttribute attributeValue, tblAttributeDefinition attributeDef
    WHERE 
        item.Id = attributeValue.fkItemId 
        AND item.Deleted = 0
        AND item.PendingPublish = 0 
        AND attributeValue.fkAttributeDefinitionId = attributeDef.Id
        AND attributeDef.[Name] = 'Color'
    ORDER BY item.Published DESC
END;

有时,程序的执行以例外结束:

SqlException: Transaction (Process ID 66) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

有谁知道如何重写程序以避免异常?

在存储过程调用中是否存在“预锁定”表,因此其他代码不能中断执行?

先谢谢你的帮助!


编辑1:附加的估计执行计划

estimated execution plan


编辑2:我无法获取死锁图,因为异常仅在实时环境中每天发生几次。我不允许在实时环境中运行探查器。我无法在开发环境中重现死锁。


编辑3:我没有成功获得僵局。

1 个答案:

答案 0 :(得分:3)

  1. 发布死锁信息。见How to: Save Deadlock Graphs
  2. 发布声明此程序使用(即死锁获胜者)死锁
  3. 发布所涉及的表的完全架构,包括所有索引,群集和非群集
  4. 您的执行计划具有不少于3个聚簇索引扫描。使用计划的图片而不是实际计划,我们无法说明运算符的实际属性是什么,但这些行看起来很厚(表示大的结果)并且它们落后于并行运算符。所有这些都指向导致表扫描的错误索引策略。此类大型扫描保证与任何更新冲突。当冲突导致死锁(通常由于索引更新顺序而发生)时,作为只读操作的此查询将始终被选为受害者广告。

    一种解决方案是正确索引数据库,以便不再进行那些昂贵的表扫描。除了整体性能优势外,它还可以降低死锁冲突的可能性。

    如果死锁仍然存在,那么答案将非常具体,具体取决于实际的死锁情况。

    对于一个神奇的“预锁定”策略,你可以拿一把大锤并用或者TABLOCK甚至TABLOCKX提示来装饰你的查询,但性能会很快消失。正确的解决方案是解决死锁问题,而不是强制序列化。