Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
线程安全sql事务,如何在事务期间锁定特定行?_Sql_Sql Server_Multithreading_Sql Server 2008 - Fatal编程技术网

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

线程安全sql事务,如何在事务期间锁定特定行?,sql,sql-server,multithreading,sql-server-2008,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 + @cos

我有这样一个程序:

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
在这个事务期间,我需要从oFoo表中用Foo=@Foo锁定该行,这样就没有人可以读取/编辑/删除它,有人知道怎么做吗

我正在使用Microsoft SQL Server 2008

请参阅:

以及:

请特别注意MSDN页面:

READ COMMITTED

Specifies that statements cannot read data that has been modified but not committed
by other transactions. This prevents dirty reads. Data can be changed by other
transactions between individual statements within the current transaction, resulting
in nonrepeatable reads or phantom data. This option is the SQL Server default.
(基于SQL Server)

我认为当涉及到表格提示时,你需要进行实验(TABLOCK,TABLOCKX),看看哪个最适合你。还要注意,查询优化器可能会忽略这些提示。如果查询优化器未选择表并在后续查询计划中使用该表,则将忽略表级提示


关于这个主题的另一篇有用的文章,虽然有点旧,因为它是基于SQL Server 2000的。

如果您不想让任何人更新/删除行,我将使用SELECT语句中的UPDLOCK。这表示您将很快更新同一行,例如

select @Bar = Bar from oFoo WITH (UPDLOCK) where Foo = @Foo;
现在,如果您想要没有人能够读取值的情况,我会使用ROWLOCK(+HOLDLOCK XLOCK)使其成为独占的,并一直保持到事务结束

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

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

CREATE TABLE ##temp (a int, b int)
INSERT INTO ##temp VALUES (0, 0)
客户#1

客户#2:


我认为简单地选择一行通常会在事务范围内锁定它,除非您重新配置了数据库。试试看?还有其他人吗?@martinr:SELECT将放置一个共享锁,例如,数据在SELECT和第一次更新之间仍然可以修改。您需要告诉我们您使用的是哪个数据库,根据数据库的不同,可能会有特定的方法。@ligget78,哦,比我当时暗示的要多一些。。。!锁的种类很重要!我使用的是MicrosoftSQLServer2008,也许应该扩展一下updlock可能会采用页锁或行锁,这取决于各种因素。
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
begin tran
select * from ##temp where a = 0 or a = 1
commit tran