困惑于UPDLOCK,HOLDLOCK
在研究使用表格提示时,我遇到了这两个问题:
我应该使用哪些锁定提示(T-SQL)?
HOLDLOCK对UPDLOCK有什么影响?
  这两个问题的答案都表明,在使用(UPDLOCK, HOLDLOCK) ,其他进程将无法读取该表上的数据,但我没有看到这一点。  为了测试,我创建了一个表并启动了两个SSMS窗口。  从第一个窗口中,我使用各种表提示从表中选择了一个事务。  当交易正在运行时,从第二个窗口开始,我运行各种语句来查看哪些内容会被阻止。 
测试表:
CREATE TABLE [dbo].[Test](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](50) NULL,
 CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
从SSMS窗口1:
BEGIN TRANSACTION
SELECT * FROM dbo.Test WITH (UPDLOCK, HOLDLOCK)
WAITFOR DELAY '00:00:10'
COMMIT TRANSACTION
从SSMS Window 2(运行以下任一项):
SELECT * FROM dbo.Test
INSERT dbo.Test(Value) VALUES ('bar')
UPDATE dbo.Test SET Value = 'baz' WHERE Value = 'bar'
DELETE dbo.Test WHERE Value= 'baz'
不同的表格提示对窗口2中运行的语句的影响:
           (UPDLOCK)       (HOLDLOCK)    (UPDLOCK, HOLDLOCK)    (TABLOCKX)
---------------------------------------------------------------------------
SELECT    not blocked      not blocked       not blocked         blocked
INSERT    not blocked        blocked           blocked           blocked
UPDATE      blocked          blocked           blocked           blocked
DELETE      blocked          blocked           blocked           blocked
  我误解了这些问题中给出的答案,还是在测试中犯了错误?  如果没有,为什么你会单独使用(UPDLOCK, HOLDLOCK)和(HOLDLOCK) ? 
进一步解释我试图完成的事情:
我想从表中选择行,并防止在处理它时修改该表中的数据。 我不修改该数据,并希望允许读取发生。
  这个答案清楚地表明(UPDLOCK, HOLDLOCK)会阻止读取(不是我想要的)。  对这个答案的评论意味着它是HOLDLOCK ,防止读取。  为了更好地理解表格提示的效果,并确定UPDLOCK是否能够做到我想做的,我做了上述实验并得到了与这些答案相矛盾的结果。 
  目前,我认为(HOLDLOCK)是我应该使用的,但是我担心我可能犯了一个错误或者忽略了将来会咬我的东西,所以这个问题。 
  为什么UPDLOCK块会选择?  锁兼容性矩阵清楚地显示了S / U和U / S争用的N ,如同在“ 无冲突”中一样 。 
至于HOLDLOCK提示文档指出:
HOLDLOCK:相当于SERIALIZABLE。 有关更多信息,请参阅本主题后面的SERIALIZABLE。
...
SERIALIZABLE:...使用与在SERIALIZABLE隔离级别上运行的事务相同的语义执行扫描...
事务隔离级别“主题解释了SERIALIZABLE的含义:
在当前事务完成之前,没有其他事务可以修改当前事务读取的数据。
其他事务不能插入具有键值的新行,这些键值落在当前事务中任何语句读取的键的范围内,直到当前事务完成。
因此,您看到的行为完全可以通过产品文档来解释:
SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ... 真正的问题是你想达到什么目的? 玩锁定提示没有完全理解110%的锁定语义是需要麻烦的...
编辑完成后:
我想从表中选择行,并防止在处理它时修改该表中的数据。
您应该使用较高的事务隔离级别之一。 REPEATABLE READ将防止您读取的数据被修改。 SERIALIZABLE将阻止您读取的数据被修改并插入新的数据。 使用事务隔离级别是正确的方法,而不是使用查询提示。 肯德拉小有一个很好的海报,放宽了隔离水平。
当您希望在未来的更新语句的select语句中锁定一行或多行时使用UPDLOCK。 未来的更新可能是交易中的下一个陈述。
其他会话仍然可以看到数据。 他们无法获得与UPDLOCK和/或HOLDLOCK不兼容的锁。
当你想让其他会话不会改变你锁定的行时,你可以使用UPDLOCK。 它限制了他们更新或删除锁定行的能力。
当您想让其他会话不会更改您正在查看的任何数据时,可以使用HOLDLOCK。 它限制了他们插入,更新或删除已锁定行的能力。 这允许您再次运行查询并查看相同的结果。
链接地址: http://www.djcxy.com/p/5611.html