Потокобезопасная транзакция SQL, как заблокировать определенную строку во время транзакции? - PullRequest
7 голосов
/ 17 декабря 2009

У меня есть такая процедура:

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

Мне нужно заблокировать строку с помощью Foo = @Foo из таблицы oFoo во время этой транзакции, чтобы никто не мог прочитать / отредактировать / удалить ее, кто-нибудь знает, как это сделать?

Я использую Microsoft SQL Server 2008

Ответы [ 3 ]

10 голосов
/ 17 декабря 2009

Если вы не хотите, чтобы кто-либо обновлял / удалял строку, я бы добавил UPDLOCK в оператор SELECT. Это указывает на то, что вы скоро обновите ту же строку, например

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

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

клиент № 2:

begin tran
select * from ##temp where a = 0 or a = 1
commit tran
1 голос
/ 17 декабря 2009

(на основе SQL Server)

Я думаю, что когда речь заходит о табличных подсказках, вам нужно поэкспериментировать (TABLOCK, TABLOCKX) и посмотреть, что подходит вам больше всего. Также имейте в виду, что оптимизатор запросов может игнорировать подсказки. Подсказки на уровне таблицы будут игнорироваться, если таблица не выбрана оптимизатором запросов и не используется в последующем плане запросов.

Еще одна полезная статья на эту тему, хотя она немного устарела и основана на SQL Server 2000: Советы по блокировке таблицы SQL Server 2000

1 голос
/ 17 декабря 2009

См .: http://www.mssqlcity.com/Articles/Adm/SQL70Locks.htm

А: http://msdn.microsoft.com/en-us/library/ms173763.aspx

Обратите особое внимание на страницу 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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...