Załóżmy, że masz następujący kod (zignoruj, że jest okropny):
BEGIN TRAN;
DECLARE @id int
SELECT @id = id + 1 FROM TableA;
UPDATE TableA SET id = @id; --TableA must have only one row, apparently!
COMMIT TRAN;
-- @id is returned to the client or used somewhere else
Moim zdaniem NIE jest to właściwe zarządzanie współbieżnością. To, że masz transakcję, nie oznacza, że ktoś nie przeczyta tej samej wartości, co ty, zanim przejdziesz do wyciągu z aktualizacji.
Teraz, pozostawiając kod bez zmian (zdaję sobie sprawę, że lepiej jest traktować go jako pojedynczą instrukcję, a nawet lepiej, używając kolumny autoinkrementacji / tożsamości), jakie są pewne sposoby na poprawne obsługiwanie współbieżności i zapobieganie warunkom wyścigu, które pozwalają dwóm klientom uzyskać to samo wartość id?
Jestem prawie pewien, że dodanie a WITH (UPDLOCK, HOLDLOCK)
do SELECT załatwi sprawę. SERIALIZABLE poziom izolacji transakcji byłoby wydaje się działać jak dobrze, ponieważ zaprzecza ktoś czytać to, co zrobiłeś, aż tran jest skończona ( UPDATE :. Ta odpowiedź jest fałszywa Zobacz Martin). Czy to prawda? Czy oba będą działać równie dobrze? Czy jedno jest lepsze od drugiego?
Wyobraź sobie, że wykonujesz coś bardziej uzasadnionego niż aktualizacja identyfikatora - niektóre obliczenia na podstawie odczytu, który musisz zaktualizować. Może być zaangażowanych wiele tabel, z których niektóre napiszesz, a inne nie. Jaka jest tutaj najlepsza praktyka?
Po napisaniu tego pytania, myślę, że wskazówki blokujące są lepsze, ponieważ wtedy blokujesz tylko te tabele, których potrzebujesz, ale byłbym wdzięczny za wkład każdego.
PS I nie, nie znam najlepszej odpowiedzi i naprawdę chcę uzyskać lepsze zrozumienie! :)
update
które może być oparte na nieaktualnych danych? Jeśli to drugie, możesz użyćrowversion
kolumny, aby sprawdzić, czy wiersz, który ma zostać zaktualizowany, nie został zmieniony od momentu jego odczytania.