【问题标题】:tsql transaction level row wise lockingtsql 事务级逐行锁定
【发布时间】:2014-03-27 06:20:17
【问题描述】:

如果我的英语不好,首先很抱歉。

我遇到了关于事务隔离级别的问题。我当前的隔离级别是读取提交的。但它有时会导致表死锁。 例如

create table tmp(id int,name varchar(20))
insert into tmp(id,name)
values(1,'Binesh')
       ,(2,'Bijesh')
       ,(3,'Bibesh')
begin transaction
update tmp set name ='Harish' where id=2

我正在尝试进入另一个查询窗口

   select * from tmp where id=1

它正在锁定表,因此在我回滚或提交第一个记录之前它不会提供任何记录

我试过了

ALTER DATABASE db
SET READ_COMMITTED_SNAPSHOT On
ALTER DATABASE db
SET ALLOW_SNAPSHOT_ISOLATION on

它不会锁定表,但它会为 id =2 提供旧值

select * from tmp where id=2 

返回我期待锁定的 Bijesh

我希望像 if id=1 这样的方式可以正常工作,但如果 id =2 它将等到其他事务结束。

希望你的帮助.....

提前致谢

Binesh Nambiar C

【问题讨论】:

  • SQL Server NOT 锁定了表 - 它锁定了您新插入的那些行(id 值从 1 到 3)。这些无法读取 - 直到提交 INSERT
  • 使用 WITH NOLOCK 将解决您的问题
  • 感谢您的重播,并非常感谢您为我提出问题。到目前为止,我还认为 marc 告诉我(过去 10 年)。但目前一些项目开始出现死锁,它们在计划任务中。这个实验的线索。在我的示例中,插入不在任何事务下。如果您有疑问,请在查询窗口中尝试一次...
  • 嗨 mohan,witn(nolock) 不是我所期望的。它作为未提交的隔离级别读取。我期待行级锁定。但我能够获得表锁定或不锁定。
  • 你忘记调用 commit 结束事务

标签: sql sql-server tsql transactions


【解决方案1】:

这不是您遇到的死锁。

您的第二个查询被阻止,因为它必须扫描整个表。在扫描过程中遇到了正在更新的行(排他锁),所以一直等到锁被释放(即事务结束)。

如果引擎知道 id 列是唯一的(主键或唯一约束),您将不会在此处阻塞,因为它不必对整个表进行扫描,而是在第一次匹配时停止。

保持 ypur 事务简短,提供对数据(索引)的替代访问路径,并尽量不要使用“select *”。

另外,请仔细考虑您是否真的要使用 READ UNCOMMITTED 隔离级别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-29
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多