Ориентированная на многопотоковое исполнение sql транзакция, как заблокировать определенную строку во время транзакции?

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

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

7
задан Sam Saffron 17 December 2009 в 23:06
поделиться

3 ответа

Если вы хотите, чтобы никто не обновлял / удалял строку, я бы использовал 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
10
ответ дан 6 December 2019 в 21:14
поделиться

См .: 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.
1
ответ дан 6 December 2019 в 21:14
поделиться

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

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

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

1
ответ дан 6 December 2019 в 21:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: