我已经运行了这个SQL,
create table temp
(
id int,
name varchar(10)
)
insert into temp values(1,'a');
然后我跑,
select 1 from temp where id = 1
一切都很好。
然后我运行一个未提交的插入
SET NOCOUNT ON;
DECLARE @TranCount INT;
SET @TranCount = @@TRANCOUNT;
IF @TranCount = 0
BEGIN TRANSACTION
ELSE
SAVE TRANSACTION Insertorupdatedevicecatalog;
insert into temp values(2,'b')
然后我跑,
select 1 from temp where id = 1
但这次没有任何回复。为什么我的完整表被锁定而不仅仅是第二行?
答案 0 :(得分:6)
SQL Server没有锁定整个表。我可以看到写入事务锁定了单个row-id。
读者必须扫描整个表,因为没有索引。
这意味着它被插入行上的X锁定阻止。基本上,读者等待另一个事务来决定是否要实际提交此行或回滚。
会话51已插入id 2.会话54是被阻止的选择。这里没有页面或表锁(除了这里没关系的意图锁)。
表是堆的事实(没有像通常那样的唯一CI)会导致意外锁定。通过在ID上创建唯一的CI,此问题将消失。
答案 1 :(得分:2)
我的猜测是你的桌子本身可能没有被锁定(或者可能是因为你的行数很少)。我认为发生的事情是SQL Server为了知道在哪里插入新行,必须锁定(写锁定,这会阻止读取)插入值周围的一系列行。由于表中的行数很少,因此表格是锁定的。当您添加更多行时,插入单行时不应该看到此行为。
顺便说一句,您的表应该有一个主键和/或聚簇索引。这将有助于将来添加更多行。否则你将进行扫描,这肯定会延长进行更新(也许是插入)所需的时间。