困惑于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