Pytanie o warunki wyścigu serwera SQL

(Uwaga: dotyczy MS SQL Server)

Załóżmy, że masz tabelę ABC z kolumną tożsamości klucza podstawowego i kolumną CODE. Chcemy, aby każdy wiersz tutaj posiadał unikalny, generowany sekwencyjnie kod (oparty na typowej formule cyfr kontrolnych).

Powiedzmy, że masz kolejną tabelę DEF z tylko jednym wierszem, w której przechowywany jest następny dostępny KOD (wyobraź sobie prosty numer wiersza).

Wiem, że logika taka jak poniżej przedstawia sytuację wyścigu, w której dwóch użytkowników może otrzymać ten sam KOD:

1) Run a select query to grab next available code from DEF
2) Insert said code into table ABC
3) Increment the value in DEF so it's not re-used.

Wiem, że dwóch użytkowników może utknąć w kroku 1) i może skończyć się tym samym KODEM w tabeli ABC.

Jaki jest najlepszy sposób radzenia sobie z tą sytuacją? Pomyślałem, że mogę po prostu zawinąć tę „logikę startu” / „zatwierdzenia” wokół tej logiki, ale nie sądzę, żeby to działało. Przetestowałem taką procedurę zapisaną w bazie, ale nie uniknąłem sytuacji wyścigu, gdy pobiegłem z dwóch różnych okien w MS:

begin tran

declare @x int

select   @x= nextcode FROM  def

waitfor delay '00:00:15'

update def set nextcode = nextcode + 1

select @x

commit tran

Czy ktoś może rzucić na to trochę światła? Pomyślałem, że transakcja uniemożliwi innemu użytkownikowi dostęp do mojej tabeli NextCodeTable, dopóki pierwsza transakcja nie zostanie zakończona, ale myślę, że zrozumienie transakcji jest błędne.

EDYTUJ: Próbowałem przenieść czekanie po instrukcji „aktualizacja” i dostałem dwa różne kody ... ale podejrzewałem to. Mam tam polecenie waitfor, aby zasymulować opóźnienie, dzięki czemu można łatwo zobaczyć stan wyścigu. Myślę, że kluczowym problemem jest moje błędne postrzeganie działania transakcji.

questionAnswers(7)

yourAnswerToTheQuestion