Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server书签查找死锁解决方案_Sql Server_Sql Server 2008_Deadlock_Isolation Level_Snapshot Isolation - Fatal编程技术网

Sql server SQL Server书签查找死锁解决方案

Sql server SQL Server书签查找死锁解决方案,sql-server,sql-server-2008,deadlock,isolation-level,snapshot-isolation,Sql Server,Sql Server 2008,Deadlock,Isolation Level,Snapshot Isolation,我在应用程序中检测到书签查找死锁,无法决定使用哪种解决方案。它们似乎都不是最优的 以下是查询: UPDATE TEST SET DATA = @data WHERE CATEGORY = @cat SELECT DATA, EXTRA_COLUMN FROM TEST WHERE CATEGORY = @cat 问题在于类别和数据中存在一个未聚集的索引,这两个查询使用该索引的顺序与聚集索引的顺序相反 i、 例如:更新锁定聚集索引并更新表,而选择锁定未聚集索引以进行书签查找,两者都希望彼此

我在应用程序中检测到书签查找死锁,无法决定使用哪种解决方案。它们似乎都不是最优的

以下是查询:

 UPDATE TEST SET DATA = @data WHERE CATEGORY = @cat

 SELECT DATA, EXTRA_COLUMN FROM TEST WHERE CATEGORY = @cat
问题在于类别和数据中存在一个未聚集的索引,这两个查询使用该索引的顺序与聚集索引的顺序相反

i、 例如:更新锁定聚集索引并更新表,而选择锁定未聚集索引以进行书签查找,两者都希望彼此锁定(死锁)

以下是我发现的选项:

1-创建包含select查询中所有列的索引。 -这是可行的,但我认为这不是一个好主意,我必须包含在任何select查询中使用的任何列,这些列可以在应用程序中的任何位置进行更新

2-将数据库的事务隔离级别更改为提交的\u快照

3-将NOLOCK提示添加到select

4-删除索引

5-在一个事务有机会获得最终阻塞另一个事务的锁之前,强制其中一个事务在较早的时间点阻塞。(不起作用)

我认为第二个选项是最好的选择,但我知道它会产生其他问题,提交的快照不应该是SQL SERVER中的默认隔离级别吗

在我看来,应用程序或数据库逻辑中都没有任何错误,只是一个简单的表,其中有一个未聚集的索引和两个访问同一个表的查询,一个用于更新,另一个用于选择

解决这个问题的最好办法是什么?还有其他解决办法吗


我真的希望SQL Server能够自己解决这个问题。

请尝试在类别(包括数据和额外列)上添加一个非聚集索引,并在查询中添加以下提示:

UPDATE t SET t.DATA = @data FROM TEST WITH (index(ix_Cat)) WHERE CATEGORY = @cat

SELECT DATA, EXTRA_COLUMN FROM TEST WITH (index(ix_Cat)) WHERE CATEGORY = @cat

这将确保两个查询将以相同的顺序更新/选择数据,并防止它们彼此死锁。

快照隔离是从等式中删除读取数据的一个非常可靠的解决方案。许多RDBMS都始终启用它们。它们在实践中不会造成很多问题。与某些手动脆弱解决方案(如非常具体的索引或提示)相比,更喜欢此解决方案。

最好的选择可能是调整查询,使它们不会相互死锁。您可以将查询包括在问题中吗?问题是一个查询会更新另一个查询索引中使用的列。一个简单的“select*from”和一个更新,从上一个select更改未聚集索引中使用的任何列,都将导致死锁。锁定/阻塞可能是不可避免的,但这并不意味着无法避免死锁。在没有看到实际查询的情况下很难说清楚。只包括了查询和死锁原因的简要描述。您在问题中提到了2个表,但查询中只引用了1个表。我同意您的看法,但遗憾的是,它可能会导致其他错误。
读取提交的快照
很少会导致错误或问题。你需要设计案例来发现问题。它们确实存在,但比一直担心读取不一致和读取查询死锁要糟糕得多。SI是一个非常好的通用解决方案。非常不受重视,因为默认情况下它是关闭的,并且理解得很少。在阅读更多关于快照隔离级别的信息时,我注意到存在一种不同的冲突,即更新冲突。这不是继续使用readcommitted隔离级别的一个很好的理由吗?我如何保证更新冲突不会发生?我通常推荐SI用于只读查询(无需思考)和具有保证不重叠数据的写查询。在其他情况下,不同的隔离级别可能更合适。在你的问题中,我会选择使用SI。问题是,我需要修复每个使用相同索引的select查询,任何其他开发人员都必须知道这一点。