Zasadniczo opisujesz klasyczny przepływ pracy oparty na kolejce i powinieneś rozważyć użycie prawdziwego kolejka .
Ze względu na dyskusję, oto jak osiągnąć to, czego chcesz:
- zażądaj określonego zasobu:
SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK) WHERE key = @key
. Zablokuje się, jeśli zasób został już odebrany. Użyj limitów czasu blokady, aby zwrócić wyjątek, jeśli zasób został już zajęty.key
musi być indeksowane i niepowtarzalne. - następny dostępny zasób:
SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK, READPAST) ORDER BY <accessorder>
. Musisz zdefiniować kolejność, aby wyrazić preferencje zasobów (najstarsze, o najwyższym priorytecie itp.) - zwolnij zajęty zasób:
COMMIT
Twoja transakcja.
Istotą problemu jest używanie właściwych wskazówek dotyczących blokad, a ten rodzaj problemu wymaga do rozwiązania wyraźnych wskazówek dotyczących blokad. UPDLOCK będzie działać jako blokada „roszczenia”. ROWLOCK tworzy odpowiednią szczegółowość, zapobiegając „optymalizacji” serwera do blokady strony. READPAST pozwala pominąć przejęte zasoby. Umieszczenie UPDLOCK w wierszach spowoduje zablokowanie wiersza i umożliwi jego późniejszą aktualizację, ale zapobiegnie innym operacjom, takim jak zwykłe polecenia SELECT zatwierdzone do odczytu, które zablokują zablokowany wiersz. Pomysł polega na tym, że i tak zamierzasz UAKTUALNIĆ wiersz, co umieści nieuniknioną blokadę X. Jeśli chcesz, aby tabela była bardziej dostępna, możesz użyć blokad aplikacji zamiast tego, ale znacznie trudniej jest go poprawnie ściągnąć. Będziesz musiał zażądać blokady aplikacji na deskryptorze ciągu zasobu, takim jak wartość klucza lub CHECKSUM
klucza lub jest to %%LOCKRES%%
wartość. Blokady aplikacji pozwalają oddzielić zakres „roszczenia” od transakcji, żądając blokady aplikacji w zakresie „sesji”, ale wtedy musisz ręcznie zwolnić roszczenie (blokady aplikacji objęte zakresem „transakcji” są zwalniane w momencie zatwierdzenia) . Uwaga, istnieje tysiąc sposobów na strzelenie sobie w stopę za pomocą blokad aplikacji.