SQL Server允许读取具有独占锁的行

时间:2018-02-26 10:39:42

标签: sql-server locking transaction-isolation

最近我遇到了与Microsoft SQL Server锁定相关的场景,看起来很简单。但是我很难理解其中一个场景背后的真实概念。

我在SQL Server中使用以下语句创建了一个名为locktest的表:

CREATE TABLE [dbo].[LockTest]
(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [name] [nvarchar](50) NULL,
    [age] [int] NULL,

    CONSTRAINT LockTest_PK PRIMARY KEY (id)
);

然后我在该表中插入了几条记录,然后在该表上运行了以下脚本。

begin tran

update locktest 
set age = 1 
 where id = 3

然后我运行了另一个SQL查询来查找上述事务生成的锁。

SELECT 
    dm_tran_locks.request_session_id,
    dm_tran_locks.resource_database_id,
    DB_NAME(dm_tran_locks.resource_database_id) AS dbname,
    CASE
       WHEN resource_type = 'OBJECT'
           THEN OBJECT_NAME(dm_tran_locks.resource_associated_entity_id)
       ELSE OBJECT_NAME(partitions.OBJECT_ID)
    END AS ObjectName,
    partitions.index_id,
    indexes.name AS index_name,
    dm_tran_locks.resource_type,
    dm_tran_locks.resource_description,
    dm_tran_locks.resource_associated_entity_id,
    dm_tran_locks.request_mode,
    dm_tran_locks.request_status
FROM 
    sys.dm_tran_locks
LEFT JOIN 
    sys.partitions ON partitions.hobt_id = dm_tran_locks.resource_associated_entity_id
LEFT JOIN 
    sys.indexes ON indexes.OBJECT_ID = partitions.OBJECT_ID 
                AND indexes.index_id = partitions.index_id
WHERE 
    resource_associated_entity_id > 0
    AND resource_database_id = DB_ID()
ORDER BY 
    request_session_id, resource_associated_entity_id 

此交易产生了3个锁。

enter image description here

在那里你可以看到已经获得了要更新的行的独占(X)锁。现在理论上没有其他操作可以读取此行,因为共享锁与独占锁不兼容。但是,当我运行如下的select查询来查询同一行时,即使上述事务尚未提交或回滚,它也会立即返回结果。

begin tran

    select * 
    from LockTest

rollback tran

为什么SQL Server允许使用独占锁读取行?感谢您的帮助

谢谢, Keth

1 个答案:

答案 0 :(得分:1)

独占锁在索引上。如果这是非聚簇的,则SELECT语句可能不使用它。 如果更新正在更改值,则表上将只有一个独占锁。如果新旧值相同,则不会进行锁定。

相关问题