为什么不是死锁而是阻塞?

typhoon1997 2013-04-10 06:34:16
数据库是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发现数据太多了,以我的智慧和武功无法解释:(
...全文
175 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
szm341 2013-04-13
  • 打赏
  • 举报
回复
1在有索引的情况下,索引定位行,而且数量较少可以视为加了rowlock 2在没有索引的情况下,rowlock的范围就较大了,可能升级为页锁或表锁,这样就产生了阻塞
最爱午夜 2013-04-12
  • 打赏
  • 举报
回复
你这个是测试阻塞,当第一个事务锁定一行数据,而第二个事务想去读取时,就会发生阻塞, 还有一种情况,如果你把两个事务提交,然后再按你试验的步骤执行,就会出现死锁,因为你虽然使用了修改数据,实际上数据的值还是前一个值,这样的话就会出现死锁,并提示牺牲掉了一个进程。
typhoon1997 2013-04-10
  • 打赏
  • 举报
回复
因为我建的是非聚集索引,所以不会有key锁的。 这次我又在窗口1和2中分别只运行waitfor delay '00:00:05'之前的sql,发现不建索引的话,确实2会被block,建的话1、2都正常。接着再查sys.dm_tran_locks,发现无论是否建立索引,窗口1中都是在资源RID上是X锁,PAGE和OBJECT上是IX锁,这点好理解。但在窗口2中,不建索引的话,在RID上是U锁,PAGE上是IU锁,OBJECT上是IX锁;建索引的话在RID上是X锁,PAGE上是IX锁,OBJECT上是IX锁。这又这么解释呢?
SQL77 2013-04-10
  • 打赏
  • 举报
回复
第一次有索引.1.2各自对键值有索引KEY锁定.互相获取不到锁 第二次没索引.直接表锁.2根本不可能有获取的机会.1你一直没提交.所以2不可能提交得了

22,206

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧