拥有由脚本[1]定义的表,我在SSMS的两个窗口中执行脚本
--1) first in first SSMS window
set transaction isolation level READ UNCOMMITTED;
begin transaction;
update aaa set Name ='bbb'
where id=1;
-- results in "(1 row(s) affected)"
--rollback
之后1)
--2)after launching 1)
select * from aaa --deleted comments
where id<>1
--is blocked
独立于1)窗口中的事务隔离级别,2)中的SELECT被阻止 为什么?
UPDATE的隔离级别对其他事务的语句有影响吗?
最高隔离级别默认为READ COMMITTED 2)
没有范围锁定,SELECT应该遭受COMMITTED READS(NONREPEATABLE READs)和PHANTOM READS(可重复读取)问题[2]
如何让它受苦?
如何在不阻止SELECT的情况下进行UPDATE?
[1]
CREATE TABLE aaa
(
Id int IDENTITY(1,1) NOT NULL,
Name varchar(13) NOT NULL
)
insert into aaa(Name)
select '111' union all
select '222' union all
select '333' union all
select '444' union all
select '555' union all
select '666' union all
select '777' union all
select '888'
[2]
点击
后复制并粘贴或添加尾随)
http://en.wikipedia.org/wiki/Isolation_(database_systems)
更新:
SELECT WITH(NOLOCK)未被阻止......
UPDATE2:
或者,与之相同,READ UNCOMMITTED
请注意,UPDATE与SELECT行不同 即使如果相同,这种行为也与隔离级别的描述相矛盾[2]
要点是:
SQL Server 2008 R2开发
答案 0 :(得分:6)
我相信这是因为你没有主键,我认为这会导致锁升级,从而阻塞了SELECT。如果在ID列上添加PRIMARY KEY,您会注意到如果再次尝试,SELECT将立即返回其他3行 - 不需要WITH(NOLOCK)提示。
答案 1 :(得分:2)
之后重复测试
--3)
create index IX_aaa_ID on aaa(id)
SELECT 2)仍被阻止
--4)
drop index IX_aaa_ID on aaa
create unique index IX_aaa_ID on aaa(id)
--or adding primary key constraint
SELECT 2)未被阻止
如果修改2)为
--2b)
select * from aaa
where id=3
--or as
--WHERE id=2
表明即使没有任何索引或PK,2b)也不会被阻止。
虽然,2b),没有任何索引,在修改1)UPDATE以在serializable下运行后被阻止 但不是在REPEATABLE READ或更低
下--1c)
set transaction isolation level serializable;
--set transaction isolation level REPEATABLE READ;
begin transaction;
update aaa set Name ='bbb'
where id=1;
--rollback
那么,看起来多行选择尝试获取不可共享的锁?
更新:
好吧,在SELECT被阻止的所有情况下,它都在等待获得LCK_M_IS
理解这道菜的好理由
UPDATE2:
好吧,它不是在表上升级的UPDATE锁,它是SELECT(共享)锁(当SELECT尝试读取多行时)被升级为表锁并且由于表已经独占而无法被授予(UPDATE)锁定。
索引的存在与否与我的主要问题无关
我将此主题的讨论转移到我提交的建议"Intent rowlocks should not be escalated to a table lock if a table already contains exclusive lock"