我在应用程序中检测到书签查找死锁,但我无法决定使用哪种解决方案。它们似乎都不是最佳的。
以下是查询:
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能够自己解决这个问题。
最佳答案
快照隔离是一种非常强大的解决方案,可以从等式中删除读取。许多 RDBMS 始终启用它们。它们在实践中不会造成很多问题。与一些手动的脆弱解决方案(例如非常具体的索引或提示)相比,更喜欢此解决方案。
关于sql-server - SQL Server书签查找死锁解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29756743/