线程安全的sql事务,如何在事务期间锁定特定的行?

Omu*_*Omu 7 sql sql-server multithreading sql-server-2008

我有这样的程序:

create procedure Checkout
@Foo nvarchar(20),
@cost float
as
begin transaction

declare @Bar nvarchar(20);
select @Bar = Bar from oFoo where Foo = @Foo;

update Foo set gold = gold - @cost where name = @Foo;
update Bar set gold = gold + @cost where name = @Bar;

delete from oFoo where @Foo = Foo;

commit transaction
Run Code Online (Sandbox Code Playgroud)

我需要在此事务期间从oFoo表中使用Foo = @Foo锁定行,以便没有人可以读取/编辑/删除它,有人知道如何做到这一点吗?

我正在使用Microsoft SQL Server 2008

lig*_*t78 10

如果你不想更新/删除行,我会在SELECT语句中使用UPDLOCK.这表明您将很快更新同一行,例如

select @Bar = Bar from oFoo WITH (UPDLOCK) where Foo = @Foo;
Run Code Online (Sandbox Code Playgroud)

现在,如果你想要没有人能够读取值的情况,我会使用ROWLOCK(+ HOLDLOCK XLOCK使其成为独占的并保持到事务结束).

您可以执行TABLOCK(X),但这将锁定整个表以供该一个事务独占访问.即使有人出现并希望在另一行上执行您的程序(例如,使用另一个@Foo值),它们也会被锁定,直到上一个事务完成.

注意:您可以使用此脚本模拟不同的方案:

CREATE TABLE ##temp (a int, b int)
INSERT INTO ##temp VALUES (0, 0)
Run Code Online (Sandbox Code Playgroud)

客户#1

BEGIN TRAN
SELECT * FROM ##temp WITH (HOLDLOCK XLOCK ROWLOCK) WHERE a = 0
waitfor delay '0:00:05'
update ##temp set a = 1 where a = 0
select * from ##temp
commit tran
Run Code Online (Sandbox Code Playgroud)

客户#2:

begin tran
select * from ##temp where a = 0 or a = 1
commit tran
Run Code Online (Sandbox Code Playgroud)