2013-12-03 24 views
6

我已经运行这个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 

而是返回这个时候什么都没有。为什么我的完整表被锁定而不是第二行?

+1

表是一堆(像通常一样没有唯一的CI)的事实在这里导致意外的锁定。通过在ID上创建唯一的CI,此问题将消失。 – usr

+0

我在本地系统上运行了代码,但无法重现它。如预期的那样,第二个“SELECT”返回1。 – SchmitzIT

+0

@SchmitzIT,我正在测试这个新的数据库,新的安装和一个全新的表 – user960567

回答

6

SQL Server未锁定整个表。我可以看到,写入事务锁定了单个行ID。

阅读器必须扫描整个表格,因为没有索引。

enter image description here

这意味着,它是通过在插入的行与X锁阻止。基本上,读者等待另一个事务来决定是否要实际提交该行或回滚。

enter image description here 会话51已经插入了id 2.会话54是被阻止的选择。这里没有页面或表格锁(除了这里无关紧要的意图锁)。

表是一堆(像通常一样没有唯一的配置项)会导致意外锁定。通过在ID上创建唯一的CI,此问题将消失。

+0

你能写出返回上述行的查询吗? – user960567

+0

如果您编写属于Session_id – user960567

+0

@ user960567的SQL语句将会很棒它是更大的脚本集合的一部分。它不是一个孤立的查询,它依赖于其他util东西的页面和页面。尝试从sys.dm_tran_locks(http://technet.microsoft.com/en-us/library/ms190345.aspx)中选择。 – usr

2

我的猜测是你的桌子本身可能没有锁定(或者可能是因为你有这么几行)。我认为发生的事情是SQL Server为了知道插入新行的位置,必须锁定(写入锁定,这会阻止读取)插入值周围的一系列行。由于表格中的行数很少,因此表格被锁定。在添加更多行时,插入单行时不应看到此行为。

顺便说一句,你的表应该有一个主键和/或聚集索引。这将有助于未来,因为您添加更多的行。否则,你将会进行扫描,这肯定会延长执行更新所需的时间(可能还会插入)。

+0

我正在测试这个新的数据库,新的安装和一个全新的表。你可以自己测试 – user960567

+0

仅供参考,我已经测试过这个更新。它与UPDATE具有相同的结果。 – user960567

+0

是的,更新将以大致相同的方式工作,表中的行数很少。当然,插入或更新应该只需要几个MS,所以锁不会长寿,用户甚至不会注意到。 –

相关问题