使用sp_getapplock可以很好地锁定数据资源吗?

时间:2016-11-15 20:12:26

标签: sql-server locking

如果有一个表有几个关于多个用户的寄存器,例如,像这样:

create table test (id int identity, userid int, data nvarchar(max));

insert into test (userid, data)
          select 1, 'aaa'
union all select 1, 'bbb'
union all select 2, 'ccc'
union all select 3, 'ddd'
union all select 3, 'eee';

运行以下更新的几个进程:

update test
set data = data + 'z'
where userid = 1;

根据更新查询的执行计划,一个更新可能会在on方向上开始更新,而另一个更新可能会在相反的方向上更新,从而导致死锁。

为了防止这种情况,可以在不锁定整个表的情况下使用sp_getapplock并锁定资源'userid_1'。这样,只有一个进程可以更新每个用户,但是仍有多个进程可以并行更新其他用户(sp_getapplock上的'userid_3'等等)。

begin transaction

sp_getapplock @Resource = 'userid_1', @LockMode = 'Exclusive'; 

update test
set data = data + 'z'
where userid = 1;

sp_releaseapplock @Resource = 'userid_1';

commit transaction

许多用户sp_getapplock能够像这样工作吗?

我问这个是因为我发现的示例使用sp_getapplock来锁定'form_1'等应用程序资源,这可能意味着sp_getapplock不需要扩展到大量资源(就像每个时刻不同用户拥有10个锁的100k用户一样)。

我会测试这个,但想知道我做错了什么。

注意:我考虑添加一个user表只是为了在事务中用一些虚拟数据更新用户记录以获得相同的效果,但这对我来说听起来不对。

1 个答案:

答案 0 :(得分:1)

这取决于你的意思"很好地扩展"。您实际上是在为数据库中的逻辑实体(在您的示例中为用户)编写自己的互斥锁。在第一个之后调用获取互斥锁将阻塞,直到释放互斥锁(或者拥有范围结束,此时隐式释放互斥锁)。这本身会降低并发性,但我认为这就是你尝试做的事情。但是为了回答有关资源使用的问题,应用程序锁使用与用于锁定表或数据页的相同基础结构。唯一的区别是你明确控制它。