日期:2014-05-17  浏览次数:20541 次

为什么不是死锁而是阻塞?
数据库是sqlServer2008 R2
1.) 建立一个测试表——
create table tbl(id int, val int)
create index idx on tbl(id)
insert into tbl select 1, 100
insert into tbl select 2, 200
2.) 在第一个查询窗口中输入(此时不要执行)——
begin tran 
update tbl set val = 1000 where id = 1
waitfor delay '00:00:05'
select * From tbl where id = 2
3.) 在第二个查询窗口中输入(此时不要执行)——
begin tran 
update tbl set val = 2000 where id = 2
waitfor delay '00:00:05'
update tbl set val = 1000 where id = 1
4.) 同时运行上两个窗口的脚本,很快能得到其中一个的死锁报错信息,符合预期。
5.)对成功执行的窗口执行rollback,为下面的测试做准备
6.)删除索引——
drop index idx on tbl
7.) 还是同时运行上两个窗口的脚本,这次其中一个窗口会很快返回数据,另一个窗口一直处于运行状态

为什么会是这样呢,谁能给个答案?
注:我未对测试数据库属性做任何额外的设置,即隔离级别是默认的READ COMMITTED,也未启用基于行版本控制的隔离级别。查看sys.dm_tran_locks发现数据太多了,以我的智慧和武功无法解释:(
死锁?阻塞?索引

------解决方案--------------------
第一次有索引.1.2各自对键值有索引KEY锁定.互相获取不到锁
第二次没索引.直接表锁.2根本不可能有获取的机会.1你一直没提交.所以2不可能提交得了
------解决方案--------------------
1在有索引的情况下,索引定位行,而且数量较少可以视为加了rowlock
2在没有索引的情况下,rowlock的范围就较大了,可能升级为页锁或表锁,这样就产生了阻塞