2012-05-24 88 views
1

我有一个非常基本的表称为标题下面,SQL死锁INSERT,UPDATE statments存储过程

TitleID - auto identity and PK 
UserID - reference key to User table 
Title - varchar 
IsPrimary - bit 

只有一个指数,这是TitleID

现在我插入记录在PK聚集索引该表格通过在READCOMMITTED事务存储过程,

此存储的过程中插入该记录与值isPrimary = 1的表和更新所有其他标题为0

INSERT INTO Titles(...) 
    VALUES (...) 

UPDATE T 
SET IsPrimary = 0 
FROM Titles T 
WHERE T.UserID = @UserID AND T.JobTitle != @Title 

当我在多用户场景中测试此问题时,我遇到了死锁问题。如果我从存储过程中删除UPDATE命令,然后一切工作完全正常...

我试图在查询列上创建非聚集索引,并尝试WITH(ROWLOCK)提示更新语句,但似乎没有任何工作。

当我运行SQL语句和查看估计执行计划,我可以看到这两个更新聚集索引,我想这是它多用户场景中失败......

我认为这是相当简单的场景很多人都应该在高交易系统中实施这种行为,但我无法找到任何有关如何解决这个问题的方法,并且我们将不胜感激。

谢谢。

回答

0

您的死锁可能是在索引资源上。

在执行计划中查找书签/密钥查找并创建一个覆盖这些字段的非聚集索引 - 这样UPDATE的“读取”数据不会与INSERT的“写入”冲突。

+0

Kev谢谢你的回复。我也认为死锁仅仅在索引资源上,但是对于实际的更新语句不是用于过滤器/查找......因为它是聚簇索引,当表中有任何变化时它需要更新(希望我的理解是正确的)并且在相同另一次插入可能会发生,这将触发死锁。你明白我的意思吗?如果我正确地理解了你关于创建非集群索引,正如我在初始文章中提到的那样,我在update语句的where子句中使用的列上创建了非索引集群,但它没有区别..其他建议? – user1414962

+0

没有插入(不管有多少并发)不应该发生死锁 - 最坏的情况是阻塞,但不会造成死锁。您确实需要检查死锁图的输出以找出锁定的确切资源 - 从这里开始很困难:) –