Mam procedurę składowaną, która zasadniczo wybiera wartości z jednej tabeli i wstawia je do drugiej, co jest rodzajem archiwizacji. Chcę uniknąć robienia tego przez wiele osób jednocześnie.
Podczas gdy ta procedura jest uruchomiona, nie chcę, aby ktokolwiek mógł ją uruchomić, jednak nie chcę serializacji, druga osoba uruchomi procedurę po jej zakończeniu.
Chcę, aby druga osoba próbująca go uruchomić, otrzymywała błąd podczas wykonywania procedury.
Próbowałem z użyciem sp_getapplock, jednak nie jestem w stanie całkowicie zatrzymać tej osoby przed uruchomieniem procedury.
Próbowałem również znaleźć procedurę z sys.dm_exec_requests i zablokować procedurę, chociaż to działa, myślę, że nie jest optymalne, ponieważ na niektórych serwerach nie mam uprawnień do uruchamiania sys.dm_exec_sql_text (uchwyt_sql).
Jak najlepiej to zrobić?
źródło
Odpowiedzi:
Aby dodać do odpowiedzi @ Tibor-Karaszi, ustawienie limitu czasu blokady nie powoduje w rzeczywistości błędu (przesłałem PR przeciwko dokumentom). sp_getapplock zwraca tylko -1, więc musisz sprawdzić zwracaną wartość. Więc tak:
źródło
Użyj sp_getapplock na początku proc i ustaw limit czasu blokady na bardzo niską wartość. W ten sposób pojawia się błąd, gdy jesteś zablokowany.
źródło
Inną opcją jest zbudowanie tabeli kontrolującej dostęp do procedury. poniższy przykład pokazuje możliwą tabelę, a także procedurę, która mogłaby z niej skorzystać.
źródło
IsLocked
w takim przypadku zresetowałbyś stan do 0? Jestem również ciekawy twojego wykorzystaniaCOALESCE
tutaj. Może@@ROWCOUNT
być zerowy po takich instrukcjachUPDATE
? Na koniec, drobna nitpick, po co umieszczać średnik przedTHROW
stwierdzeniem w tym konkretnym przypadku?Myślę, że próbujesz rozwiązać problem w niewłaściwy sposób. To, czego chcesz, to najwyższa ochrona spójności bazy danych. Jeśli dwie osoby jednocześnie uruchamiają procedurę składowaną, spójność bazy danych może zostać naruszona.
Aby zabezpieczyć się przed różnego rodzaju niespójnościami w bazie danych, standard SQL ma cztery poziomy izolacji transakcji:
Jednak standard SQL ma podejście oparte na blokowaniu tych niespójności z bazami danych, a ze względu na wydajność wiele baz danych stosuje podejście oparte na izolacji migawek, które zasadniczo ma następujące poziomy:
Anulowanie transakcji w tych bazach danych opartych na izolacji migawek może wydawać się niepokojące, ale znowu każda baza danych anuluje transakcję z powodu impasu, więc każda rozsądna aplikacja i tak musi móc ponownie spróbować przeprowadzić transakcję.
Co chcesz jest SERIALIZABLE poziom izolacji: zapewnia, że jeśli transakcje wykonywane niezależnie jeden po drugim wynikiem w stanie dobrym, każda równoległa realizacja transakcji powoduje również stan dobry. Na szczęście Michael Cahill w swojej rozprawie doktorskiej dowiedział się, w jaki sposób SERIALIZABLE poziom izolacji może być obsługiwany przez migawkowe izolowane bazy danych przy niewielkim wysiłku.
Jeśli używasz poziomu izolacji SERIALIZABLE w izolowanej bazie danych migawek, jeśli dwie osoby spróbują uruchomić procedurę składowaną jednocześnie i staną sobie na palcach, jedna z transakcji zostanie anulowana.
Czy SQL Server rzeczywiście obsługuje poziom izolacji SERIALIZABLE (zamiast maskaradowej izolacji migawki za słowem kluczowym SERIALIZABLE )? Szczerze mówiąc, nie wiem: jedyną znaną bazą danych, która ją obsługuje, jest PostgreSQL.
Mimo że nie udzieliłem porady SQL Serverowi, nadal zamieszczam tę odpowiedź, ponieważ użytkownicy PostgreSQL i użytkownicy innych baz danych, którzy mogą rozważyć przejście na PostgreSQL, mogą skorzystać z mojej odpowiedzi. Ponadto użytkownicy baz danych innych niż PostgreSQL, którzy nie mogą przełączyć się na PostgreSQL, mogą wywierać presję na swojego ulubionego dostawcę bazy danych, aby zaoferował autentyczny SERIALIZABLE poziom izolacji.
źródło
Zdaję sobie sprawę, że „prawdziwy” problem może być bardziej złożony.
W przeciwnym razie: jeśli archiwizujesz za pomocą wyzwalaczy wstawiania i / lub aktualizacji, możesz uniknąć problemu, który próbujesz rozwiązać.
Mam nadzieję, że to pomaga,
Chris C.
źródło
the 'real' problem may be more complex
. W przypadku, gdy tak nie jest, wyzwalacze są dobrym rozwiązaniem. Ponadto prawdopodobnie łatwiej będzie je przetestować i konserwować, ponieważ jest to funkcja bazy danych zamiast niestandardowego rozwiązania.