Piszę procedurę, która będzie uzgadnianie transakcji finansowych w żywej bazie danych. Praca, którą wykonuję, nie może być wykonana jako operacja ustawiona, więc używam dwóch zagnieżdżonych kursorów.Prawidłowy sposób na wyłączny blokadę
Potrzebuję wziąć wyłączną blokadę na stole transakcji, podczas gdy ja uzgadniam na klienta, ale chciałbym zwolnić blokadę i pozwolić innym ludziom uruchomić ich zapytania pomiędzy każdym klientem, którego przetwarzam.
chciałbym zrobić wyłącznej blokady na poziomie wiersza zamiast poziomie tabeli, ale what I have read so far mówi, że nie może zrobić with (XLOCK, ROWLOCK, HOLDLOCK)
jeśli inne transakcje są uruchomione na READCOMMITED
poziom izolacji (co to jest dla mnie).
Czy przyjmuję wyłączną blokadę na poziomie stołu i czy jest jakiś sposób na serwerze 2008 R2, aby zamki wyłączne na poziomie wiersza działały tak, jak chcę, bez modyfikowania innych zapytań uruchomionych w bazie danych?
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
Próbuję dowiedzieć się, dlaczego potrzebujesz wyłącznej blokady. Czy inni ludzie mogą wstawiać rekordy? Inne osoby aktualizujące rekordy? Martwisz się, że inne osoby uzyskują niespójny widok danych? – Laurence
@ Laurence Martwię się, że inne osoby uzyskały niespójny stan wyświetlania. Próbuję poprawić błąd, który wpłynął na mały% klientów, jednak proces korygujący pozostawia kilka współzależnych wierszy w kilku tabelach (faktycznie będę blokował na 5 tabelach, ale uprościłem przykład mojego kodu do jednej tabeli) w niespójnym stanie podczas proces korekty. Ta niespójność jest izolowana na klienta, ale wykonanie "SUMIU SELECT (ColA) z trnHistory" nad tym jednym klientem zwróci nieprawidłową wartość podczas procesu "korekty". Muszę więc wybrać wyłączny zamek, aby zapobiec odczytowi. –
Nie rozumiem, dlaczego transakcja nie ochroniłaby Cię przed tym, chyba że masz ludzi robiących read_uncommitted. – Laurence