SQL Server中的永久行级锁定

Cob*_*ger 3 t-sql sql-server performance locking

我在一个存储过程上的性能非常差,它对一些非常小的表进行了超过一百次(!)的更新,并且似乎所有并发用户都在不断地相互阻塞.

程序的完全重写计划在今年晚些时候进行,但与此同时我想看看我们是否可以通过强制每个受影响的表上的行级锁定来缓解这个问题.

在Sybase上,您可以(或者至少可以在2007年左右)使用以下语句强制对表执行行级锁定:

alter table titles lock datarows
Run Code Online (Sandbox Code Playgroud)

在SQL Server上,似乎获得相同效果的唯一方法是在每个更新或插入语句上使用WITH(ROWLOCK).即便如此,它只是一个可以忽略的暗示.

SQL Server中是否有一种方法可以强制(或强烈支持)对给定表的所有更新进行行级锁定?

Rem*_*anu 9

首先要确保更新不是表扫描.换句话说,你确实有正确的索引(UPDATE也需要索引......).确保经过仔细考虑后,禁用所用索引的页锁:

ALTER INDEX ... WITH (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS = ON);
Run Code Online (Sandbox Code Playgroud)

给你的这个操作同样照顾一桶TNT和一瓶凝固汽油......


其他信息(来自以下评论):

  • 您可以在聚簇索引上禁用页锁,但是您不能禁用堆上的页锁(因为它们是物理结构的,并且无法在不锁定页面的情况下执行正确的锁定层次结构).

  • 锁定升级是一个(相关的,但是)不同的主题.如果语句选择行级锁粒度并且它决定在执行期间升级到行集粒度级别,则锁定升级才会出现.确实OP可能实际上是升级的受害者,从我读OP的方式来看,我认为更可能的原因就是缺少索引(即,由于扫描而预先选择高锁粒度,不会触发升级).

  • 初始粒度级别是手头任务的引擎估计的结果.如果估计指示必须锁定大量行,则可以选择页面粒度,因为获取大量行锁通常是有问题的.缺少索引将触发扫描,通常会选择页面粒度.

  • 升级也是从行/页到行集(对象)的粒度.首先浏览中间页面级别会遇到并发性问题,因此使用了"大锤子".