【发布时间】:2013-02-20 19:28:58
【问题描述】:
场景:
嵌入在包装器 TransactionScope(TransactionScopeOption.Required) 中的 TransactionScope(TransactionScopeOption.Suppress) 查询。在“抑制”查询之前,还有另一个与包装“必需”TransactionScope 关联的查询。
这两个查询只在一张表上重叠。前面的“必需”查询插入到表中,后面的“抑制”查询从表中选择。忽略这是多么愚蠢,“抑制”查询只会读取未锁定的行,因此不会包含新插入的结果。
行为:
我看到的行为是,如果表中有行,则插入将成功,然后选择将读取未锁定的行,然后继续。但是,如果表为空,则插入会成功,但随后 Select 会因为被插入阻塞而卡住。
问题:
我想要得到的是对在这种情况下如何跟踪锁定的概念性理解。我曾经认为表锁定是一种位切换,其中表被锁定或解锁,但它似乎更像是带有 NOT EXISTS 的 CASE 语句;在没有解锁行的情况下,表被锁定而不是表被解锁,但其中的每一行当前都处于锁定状态。
我能够找到的所有内容都表明确实存在不同级别的锁定(表、行、页面等),但我找不到任何明确说明如果表为空并且插入的数据上存在行锁,则隐含表锁。最初我预计 Select 会简单地返回 Null,但由于这不是我认为我会联系专家的行为,看看是否有人可以给我一个明确的理解。
注意事项:
关系型数据库:SQL Server 2012
.NET 框架:4.0
核心行为:如果在插入之前表中存在记录,则两个查询都成功,但如果在插入之前表为空,则选择被插入阻塞。
表:
Create Table Random(ID Int Identity, Word Varchar(50), TimeInserted DateTime)
插入查询:
Insert Random(Word, TimeInserted)
Select 'Word', GetDate()
选择查询:
Select Max(TimeInserted)
From Random
Where Word Like 'A%'
【问题讨论】:
-
您是否对选择使用可序列化隔离?还有什么是表结构和查询?
-
是可序列化的,表结构和查询应该无关紧要。 “必需”查询是一个 INSERT,它排除了作为 SELECT 的“抑制”查询。将表视为三列,一个 IDENTITY 列,一个 Varchar(50) 和一个 DateTime 列。插入添加 Varchar(50) 和 DateTime(身份自动增量),并且选择正在读取 DateTime。
-
查询和表结构确实很重要,因为这决定了它是锁定整个对象还是锁定键范围,以及如果是后者,则锁定哪个特定范围。
-
好吧,问题已更新。感谢您的帮助。
-
无论表是否为空,这些查询都应始终阻塞,除非读取未提交或快照隔离(或者如果您使用
with (readpast)提示)。插入将使用MAX(TimeInserted)添加一行,而SELECT查询在插入提交之前无法读取它。
标签: .net sql sql-server locking transactionscope