最近我遇到了与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个锁。
在那里你可以看到已经获得了要更新的行的独占(X)锁。现在理论上没有其他操作可以读取此行,因为共享锁与独占锁不兼容。但是,当我运行如下的select查询来查询同一行时,即使上述事务尚未提交或回滚,它也会立即返回结果。
begin tran
select *
from LockTest
rollback tran
为什么SQL Server允许使用独占锁读取行?感谢您的帮助
谢谢, Keth
答案 0 :(得分:1)
独占锁在索引上。如果这是非聚簇的,则SELECT语句可能不使用它。 如果更新正在更改值,则表上将只有一个独占锁。如果新旧值相同,则不会进行锁定。