选择80%的行和表锁

时间:2016-09-21 19:21:37

标签: sql sql-server sql-server-2008

我的一位同事带着这句话来找我:

  

在表上有一个WHERE,可以获取80%的行   带有索引的列的WITH (NOLOCK)子句。因此,为避免在FROM子句中添加WITH (NOLOCK)

他唯一的论点是:相信我,我自己也经历过。我找不到合适的文件。

我知道UPDATE只会影响表格,只会在选择时出现INSERT和{{1}},这可能导致我们进行脏读。

我的同事的假设是否正确?

2 个答案:

答案 0 :(得分:0)

我认为你指的是锁升级,https://technet.microsoft.com/en-us/library/ms184286(v=sql.105).aspx,结合由选择性差的索引引起的表扫描,以及阻塞的一些可能性。

如果非聚集索引的统计信息显示从表中返回的特定值的行数超过某个阈值,则优化程序将选择使用表扫描来查找相应的行而不是索引搜索相应的书签查找,因为它们的数量很慢。

我通常会告诉别人你希望这个百分比是5%或更低,但有时它仍然可以指数达到10%左右。在80%时,它肯定会进行表扫描。

此外,由于查询正在进行表扫描,因此查询必须能够在表中的每一行上获取某种锁。如果有任何其他查询正在运行执行更新,或者甚至阻止在单行上获取锁,则查询将不得不等待。

锁定升级时,它不是百分比,而是特定的幻数5000。查询通常使用行锁开始读取行。如果单个查询读取5,000行或更多行,则会将对其使用的锁从行和/或页锁升级到全表锁。

这是发生死锁的时候,因为另一个查询可能正在尝试做同样的事情。

这些锁不一定与插入/更新有关。

这是一个实际的事情。不,这并不意味着你应该使用NOLOCK。如果您遇到死锁问题,那么看看READPAST,TABLOCK或TABLOCKX https://msdn.microsoft.com/en-us/library/ms187373.aspx会好得多。

不要仅仅出于习惯而做任何这些事情,只针对遇到实际问题的高度事务表的特定实例进行调查。

答案 1 :(得分:0)

默认情况下,作家有优先权,读者会等待作家完成。 WITH(NOLOCK)将允许读者读取未提交的数据,避免等待作者完成。对于非常大的表的只读查询,如果您查询数据(例如旧数据分区)或撤回不会经常更改的数据并且更改在数据表示中并不重要,则可以。这与在SP中使用SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED指令相同。