我在我的应用程序中检测到书签查找死锁,我无法决定使用哪种解决方案。它们似乎都不是最佳的。
以下是查询:
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 能够自己解决它。