HOLDLOCK with UPDLOCK

前端 未结 3 2247
萌比男神i
萌比男神i 2020-12-31 17:22

It appears using either HOLDLOCK or UPDLOCK in a transaction (say T1), will not block read access from another transaction (say T2).

As I u

3条回答
  •  甜味超标
    2020-12-31 17:57

    I believe Martin already explained how the updlock can result in an exclusive lock (+1)... and I would rather post this as a comment / question, but my comment is too large...

    Here's a quick example of the updlock resulting in the x lock...

    IF (OBJECT_ID('tblTest') IS NOT NULL)
        DROP TABLE tblTest
    
    CREATE TABLE tblTest (
        ID INT NOT NULL
    )
    
    BEGIN TRANSACTION
        SELECT * FROM dbo.tblTest WITH (UPDLOCK, HOLDLOCK) WHERE ID = 1
        SELECT * FROM sys.dm_tran_locks WHERE request_session_id = @@SPID 
    COMMIT
    

    However, if you add a clustered index to your table, the exclusive table lock goes away, and is replaced with a RangeS-U lock...

    ALTER TABLE dbo.tblTest 
    ADD CONSTRAINT PK_tblTest 
    PRIMARY KEY CLUSTERED (ID)
    
    BEGIN TRANSACTION
        SELECT * FROM dbo.tblTest WITH (UPDLOCK, HOLDLOCK) WHERE ID = 1
        SELECT * FROM sys.dm_tran_locks WHERE request_session_id = @@SPID 
    COMMIT
    

    So basically, do you have a clustered index on this table?

    EDIT:

    Another example using a non-clustered index...

    IF (OBJECT_ID('tblTest') IS NOT NULL)
        DROP TABLE tblTest
    
    CREATE TABLE tblTest (
        ID INT NOT NULL
    )
    
    CREATE NONCLUSTERED INDEX 
    IX_tblTest ON dbo.tblTest (ID) 
    
    BEGIN TRANSACTION
        SELECT * FROM dbo.tblTest WITH (HOLDLOCK) WHERE ID = 1
        SELECT * FROM sys.dm_tran_locks WHERE request_session_id = @@SPID 
    COMMIT
    

    Will result in a RangeS-S lock...

    But...

    BEGIN TRANSACTION
        SELECT * FROM dbo.tblTest WITH (UPDLOCK, HOLDLOCK) WHERE ID = 1
        SELECT * FROM sys.dm_tran_locks WHERE request_session_id = @@SPID 
    COMMIT
    

    Will result in an exclusive table lock...

提交回复
热议问题