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

当查询条件为非主键字段时,为什么在SQLServer的更新锁(UPDLOCK)会锁表
大家能不能帮我看看,当查询条件为非主键字段时,为什么在SQLServer的更新锁(UPDLOCK)会整表锁定?

===========================================================
当我采用主键au_id列作为查询条件时,可以正常锁定查询的行:
begin tran
select * from authors with(updlock) where au_id=1
update authors set au_lname='aaa' where au_id=1
waitfor delay '00:00:30'
commit tran

上面语句中,我延时了30秒,在这30秒内:
1、另外打开第一个查询窗口,编写如下代码:(结果:正常已锁定,不能更新)
update authors set au_lname='aaa' where au_id=1

2、另外打开第二个查询窗口,编写如下代码:(结果:正常未锁定,可以更新):
update authors set au_lname='aaa' where au_id=1


=============================================================
当我采用非主键au_lname列作为查询条件时,则不能正常锁定查询的行:
begin tran
select * from authors with(updlock) where au_lname='White'
update authors set au_lname='bbb'  where au_lname='White'
waitfor delay '00:00:30'
commit tran

上面语句中,我一样延时了30秒,在这30秒内:
1、另外打开第一个查询窗口,编写如下代码:(结果:正常已锁定,不能更新)
update authors set au_lname='bbb' where au_lname='White'

2、另外打开第二个查询窗口,编写如下代码:(结果:不正常已锁定,不能更新):
update authors set au_lname='bbb' where au_lname='Green'

------解决方案--------------------
2、另外打开第二个查询窗口,编写如下代码:(结果:正常未锁定,可以更新):
update authors set au_lname='aaa' where au_id=1
例子应该是au_id=2之类的吧
-----------
准确的说不是主键的问题,而是聚集索引的缘故
数据的物理顺序是由聚集索引决定的,而且数据量少的话会精确锁定行
(一般数据量大的话都会引起锁升级)
而非聚集索引列应该是存储的聚集索引键值与对应列的数据,
所以非聚集索引锁定行的时候范围可能会大