【发布时间】:2015-06-27 16:49:57
【问题描述】:
我在我的应用程序中检测到书签查找死锁,我无法决定使用哪种解决方案。它们似乎都不是最佳的。
这里是查询:
UPDATE TEST SET DATA = @data WHERE CATEGORY = @cat
SELECT DATA, EXTRA_COLUMN FROM TEST WHERE CATEGORY = @cat
问题是在 CATEGORY 和 DATA 中有一个非聚集索引,两个查询都使用与聚集索引相反的顺序。
即:更新锁定聚集索引并更新表,而选择锁定非聚集索引以进行书签查找,并且它们都希望彼此锁定(死锁)。
以下是我找到的选项:
1 - 创建一个包含选择查询中所有列的索引。 - 它有效,但我认为这不是一个好主意,我必须包含在任何选择查询中使用的任何列,这些列可以在应用程序的任何位置更新。
2 - 将数据库的事务隔离级别更改为 COMMITTED_SNAPSHOT
3 - 向选择添加 NOLOCK 提示
4 - 删除索引
5 - 强制其中一个事务在有机会获得最终阻塞另一个事务的锁之前在较早的时间点阻塞。 (没用)
我认为第二个选项是最好的选择,但我知道它会产生其他问题,COMMITTED_SNAPSHOT 不应该是 SQL SERVER 中的默认隔离级别吗?
在我看来,应用程序或数据库逻辑中都没有任何错误,它是一个简单的表,具有非聚集索引和访问同一个表的两个查询,一个用于更新,另一个用于选择。
解决这个问题的最佳方法是什么?还有其他解决办法吗?
我真的希望 SQL Server 能够自己解决它。
【问题讨论】:
-
最好的选择可能是调整你的查询,这样它们就不会互相死锁。您可以在问题中包含查询吗?
-
问题是一个查询更新了另一个查询索引中使用的列。一个简单的 'select * from' 和一个从前一个选择更改非聚集索引中使用的任何列的更新都会死锁。
-
锁定/阻塞可能是不可避免的,但这并不意味着无法避免死锁。在没有看到实际查询的情况下很难确定。
-
只包括查询和死锁原因的简要说明。
-
您在问题中提到了 2 个表,但查询中只引用了 1 个。
标签: sql-server sql-server-2008 deadlock isolation-level snapshot-isolation