带UPDLOCK的HOLDLOCK

use*_*701 8 sql-server

它似乎使用HOLDLOCKUPDLOCK在事务中(例如T1),不会阻止来自另一个事务(比如T2)的读访问.

据我了解,在T1完成之前,HOLDLOCK将阻止T2更新/删除; 和a UPDLOCK将阻止T2的更新/删除/插入.在这两个T2中都将具有对这些记录的读访问权.

但是,HOLDLOCK, UPDLOCK即使是读取访问,也使用两个(如:)块T2.当我们同时使用它们时会发生什么?

感谢您的见解

更新:

这不是我所看到的:

例如:

在查询1中:

begin tran

select * from tblTest WITH (UPDLOCK, HOLDLOCK)

WAITFOR DELAY '00:00:10'

commit tran
Run Code Online (Sandbox Code Playgroud)

在查询2中:

select * from tblTest 
Run Code Online (Sandbox Code Playgroud)

在查询1完成之前,查询2不会产生结果.

Mar*_*ith 11

UPDLOCK影响锁的类型.这意味着SELECT声明U将采取锁而不是S锁.在默认的读取提交级别,它们将在读取数据后立即释放.

以上适用于行和页锁.对于表级锁定BOL状态

如果UPDLOCK与TABLOCK结合使用,或者由于其他原因而采用表级锁定,则将采用独占(X)锁定.

HOLDLOCK 表示您获得了可序列化的隔离语义,因此在事务结束之前不会释放锁定,并且至少会锁定查询所涵盖的整个范围以防止插入幻像.

U锁与其他兼容S的锁而不是其他U的锁(见锁兼容性矩阵),所以如果锁在了行或页级取出,这将不会阻止其他读者,除非他们也使用UPDLOCK提示.

如果由于某个对象级别X锁定被取出,则会阻止UPDLOCK读者尝试获取表格上的锁定.在您的示例查询中,尝试查看第二个查询被阻止,以查看两个事务已经/正在等待的锁.ISsys.dm_tran_locks

对于您问题中的查询

SELECT *
FROM   tblTest WITH (UPDLOCK, HOLDLOCK) 
Run Code Online (Sandbox Code Playgroud)

X如果查询计划在堆上显示扫描,您将始终锁定对象.如果是索引扫描,则它取决于所使用的锁定粒度(通常在执行至少5,000个较低级别锁定后尝试锁定升级到表级别).

  • 因为你已经指定了`HOLDLOCK`所以它需要防止[幻影](http://sqlserverpedia.com/blog/sql-server-bloggers/transaction-phenomena-%E2%80%93-part-3-the-幻像读/).您的查询读取整个表,因此保护范围免受幻像意味着它根本不允许插入任何行.要获得键范围锁定,您需要合适的索引和where子句. (2认同)