Правильный способ взять эксклюзивный замок
Я пишу процедуру, которая будет согласовывать конечные транзакции в действующей базе данных. Работу, которую я выполняю, нельзя выполнить как заданную операцию, поэтому я использую два вложенных курсора.
Мне нужно сделать эксклюзивную блокировку таблицы транзакций, пока я выполняю согласование для каждого клиента, но я бы хотел снять блокировку и позволить другим людям выполнять свои запросы между каждым клиентом, который я обрабатываю.
Я хотел бы сделать эксклюзивную блокировку на уровне строк вместо уровня таблицы, ночто я прочитал до сих пор говорит, что я не могу сделатьwith (XLOCK, ROWLOCK, HOLDLOCK)
если другие транзакции выполняются вREADCOMMITED
уровень изоляции (что для меня).
Правильно ли я использую эксклюзивную блокировку на уровне таблицы, и есть ли в Server 2008 R2 способ сделать так, чтобы монопольные блокировки на уровне строк работали так, как я хочу, без изменения других запросов, выполняемых в базе данных?
declare client_cursor cursor local forward_only for
select distinct CLIENT_GUID from trnHistory
open client_cursor
declare @ClientGuid uniqueidentifier
declare @TransGuid uniqueidentifier
fetch next from client_cursor into @ClientGuid
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
begin tran
declare @temp int
--The following row will not work if the other connections are running READCOMMITED isolation level
--select @temp = 1
--from trnHistory with (XLOCK, ROWLOCK, HOLDLOCK)
--left join trnCB with (XLOCK, ROWLOCK, HOLDLOCK) on trnHistory.TRANS_GUID = trnCB.TRANS_GUID
--left join trnClients with (XLOCK, ROWLOCK, HOLDLOCK) on trnHistory.TRANS_GUID = trnClients.TRANS_GUID
--(Snip) --Other tables that will be "touched" during the reconcile
--where trnHistory.CLIENT_GUID = @ClientGuid
--Works allways but locks whole table.
select top 1 @temp = 1 from trnHistory with (XLOCK, TABLOCK)
select top 1 @temp = 1 from trnCB with (XLOCK, TABLOCK)
select top 1 @temp = 1 from trnClients with (XLOCK, TABLOCK)
--(Snip) --Other tables that will be "touched" during the reconcile
declare trans_cursor cursor local forward_only for
select TRANS_GUID from trnHistory where CLIENT_GUID = @ClientGuid order by TRANS_NUMBER
open trans_cursor
fetch next from trans_cursor into @TransGuid
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
--Do Work here
END
fetch next from trans_cursor into @TransGuid
END
close trans_cursor
deallocate trans_cursor
--commit the transaction and release the lock, this allows other
-- connections to get a few queries in while it is safe to read.
commit tran
END
fetch next from client_cursor into @ClientGuid
END
close client_cursor
deallocate client_cursor