У меня есть процедура как это:
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
Если вы хотите, чтобы никто не обновлял / удалял строку, я бы использовал 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
См .: 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.
(На основе SQL Server)
Я думаю, что когда дело доходит до подсказок таблиц, вам нужно поэкспериментировать (TABLOCK, TABLOCKX) и посмотреть, что лучше всего подходит для вас. Также имейте в виду, что оптимизатор запросов может игнорировать подсказки. Подсказки на уровне таблицы будут проигнорированы, если таблица не выбрана оптимизатором запросов и не будет использована в последующем плане запроса.
Еще одна полезная статья по этому вопросу, хотя и немного старая, поскольку она основана на SQL Server 2000, это Подсказки по блокировке таблиц SQL Server 2000