困惑于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的含义:

    在当前事务完成之前,没有其他事务可以修改当前事务读取的数据。

    其他事务不能插入具有键值的新行,这些键值落在当前事务中任何语句读取的键的范围内,直到当前事务完成。

    因此,您看到的行为完全可以通过产品文档来解释:

  • UPDLOCK不会阻止并发的SELECT和INSERT,但会阻止T1所选行的任何UPDATE或DELETE
  • HOLDLOCK意味着SERALIZABLE,因此允许SELECTS,但阻止T1所选行的UPDATE和DELETES,以及T1所选范围内的任何INSERT(这是整个表,因此是任何插入)。
  • (UPDLOCK,HOLDLOCK):除了上述情况外,您的实验并未显示会阻止什么,即在T2中使用UPDLOCK进行的另一个事务:
    SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
  • TABLOCKX不需要解释
  • 真正的问题是你想达到什么目的? 玩锁定提示没有完全理解110%的锁定语义是需要麻烦的...

    编辑完成后:

    我想从表中选择行,并防止在处理它时修改该表中的数据。

    您应该使用较高的事务隔离级别之一。 REPEATABLE READ将防止您读取的数据被修改。 SERIALIZABLE将阻止您读取的数据被修改并插入新的数据。 使用事务隔离级别是正确的方法,而不是使用查询提示。 肯德拉小有一个很好的海报,放宽了隔离水平。


    当您希望在未来的更新语句的select语句中锁定一行或多行时使用UPDLOCK。 未来的更新可能是交易中的下一个陈述。

    其他会话仍然可以看到数据。 他们无法获得与UPDLOCK和/或HOLDLOCK不兼容的锁。

    当你想让其他会话不会改变你锁定的行时,你可以使用UPDLOCK。 它限制了他们更新或删除锁定行的能力。

    当您想让其他会话不会更改您正在查看的任何数据时,可以使用HOLDLOCK。 它限制了他们插入,更新或删除已锁定行的能力。 这允许您再次运行查询并查看相同的结果。

    链接地址: http://www.djcxy.com/p/5611.html

    上一篇: Confused about UPDLOCK, HOLDLOCK

    下一篇: What effect does HOLDLOCK have on UPDLOCK?