在Repeatable Read隔离中,应用共享锁和独占锁,直到事务结束。现在考虑下面提到的查询,它在id列上有聚簇索引,在name和col1上有非聚簇索引
Set transaction isolation level repeatable read
begin transaction
update tableA
set name = 'abc'
where id = 1
select name, col
from tableA
where id = 1
commit transaction
在这种情况下,SQL Server如何处理锁定?将两个锁 - X锁和S锁在ID为1的行上或X锁将转换为S锁。
我在这里很困惑。有人可以更多地了解这种锁定行为。
答案 0 :(得分:2)
好吧,因为它在同一个事务中,当然的SQL Server知道你已经更改/更新了什么,并且可以将它返回到你的{{1 }}。
SELECT
独占锁仅阻止 OTHER 交易在更新时读取该数据。在X
执行完毕之前,X
锁将保持不变。
如果您在COMMIT
之后暂停执行,然后切换到另一个SSMS窗口并在那里执行UPDATE
,则阻止将无法读取正在更新的行
答案 1 :(得分:1)
您可以通过启用以下跟踪标志或查看sys.dm_tran_locks视图来检查锁定/保持锁定。
请勿在生产环境中运行这些跟踪标志。
traceflags将输出消息中获取/释放的锁。
在这个测试中,似乎它正在持有X锁并且还在同一个RID上获取S锁。 sys.dm_tran_locks的输出表明实际上只保存了X锁。
您的结果可能会有所不同。
DBCC TRACEON(1200,-1,3604);
SET transaction isolation level repeatable read
BEGIN TRAN
UPDATE dbo.Customer SET name = 'peter';
SELECT * FROM dbo.Customer WHERE id = 1
DBCC TRACEOFF(1200,-1,3604);
SELECT * FROM sys.dm_tran_locks WHERE request_session_id = @@SPID
COMMIT
traceflag的输出:
进程56获取DATABASE上的S锁:13 [PLANGUIDE](类bit0 ref1)结果:好的
进程56释放对DATABASE的锁定:13 [PLANGUIDE]
DBCC执行完成。如果DBCC打印出错误消息,请联系您的 系统管理员。
进程56获取对象的IX锁定: 13:1920061926:0(类bit2000000 ref1)结果:OK
进程56在PAGE:13:1:2150(类bit2000000)上获取IU锁定 ref0)结果:好的
进程56获取RID上的U锁:13:1:2150:0(类bit2000000 ref0)结果:好的
进程56在PAGE:13:1:2150(类bit2000000)上获取IX锁定 ref0)结果:好的
进程56获取RID上的X锁定:13:1:2150:0(类bit2000000 ref0)结果:好的
(1行受影响)
过程56在PAGE:13:1:2150上获取IS锁定 (类bit2000000 ref0)结果:确定
进程56获取RID上的S锁:13:1:2150:0(类bit2000000 ref0)结果:好的
(1行受影响)
进程56释放所有锁@ 00000002E54015A8
进程56完成释放所有锁@ 00000002E54015A8
进程56释放所有锁@ 00000002E54015A8
进程56完成释放所有锁@ 00000002E54015A8
进程56释放所有锁@ 00000002E54015A8
进程56完成释放所有锁@ 00000002E54015A8
进程56释放所有锁@ 00000002E54015A8
进程56完成释放所有锁@ 00000002E54015A8
进程56释放所有锁@ 00000002E54015A8
进程56完成释放所有锁@ 00000002E54015A8
进程56释放所有锁@ 00000002E54015A8
进程56完成释放所有锁@ 00000002E54015A8
进程56释放所有锁@ 00000002E54015A8
进程56完成释放所有锁@ 00000002E54015A8
(4行(s)受影响)DBCC执行完成。如果DBCC打印错误 消息,请与您的系统管理员联系。