Oracle SQL: blokowanie wierszy w instrukcji select

celem tego postu jest wyjaśnienie, jak zablokować rekord w bazie danych Oracle za pomocą instrukcji select.

wprowadzenie

celem tego postu jest wyjaśnienie, jak zablokować rekord w bazie danych Oracle za pomocą instrukcji select. Pozwala to na zablokowanie rekordu bez konieczności jego zmiany.

chociaż może się to nie wydawać zbyt powszechnym przypadkiem użycia, prawda jest taka, że możemy go potrzebować do bardziej złożonych programów (zaimplementowanych na przykład w PL / SQL), gdzie musimy wykonać złożone walidacje przed podjęciem decyzji o aktualizacji określonego rejestru i musimy utrzymać go zablokowanym podczas tych walidacji, aby żadna inna transakcja nie mogła go jednocześnie modyfikować.

będziemy używać programisty SQL do interakcji z bazą danych i wykonywania zapytań do tego samouczka.

blokowanie tego samego rekordu

jak zwykle, zaczniemy od utworzenia prostej tabeli atrapy, do przechowywania naszych danych. Sprawdź poniższy przykład utwórz.

create table Worker(WorkerID varchar(20),WorkerName varchar(255),WorkerJob varchar(255),CONSTRAINT PK_Worker PRIMARY KEY (WorkerID));

następnie wstawimy kilka fałszywych rekordów, więc mamy dane do pracy. Wstawimy trzy rekordy, a następnie zatwierdzimy transakcję. Możesz użyć przycisku commit w menu programisty SQL lub jawnie zatwierdzić transakcję za pomocą instrukcji SQL.

insert into worker values ('1','John', 'nurse');insert into worker values ('2','Grace', 'farmer');insert into worker values ('3','Smith', 'doctor');

teraz otworzymy nowy nie udostępniony arkusz roboczy, abyśmy mogli przetestować instrukcje SQL w niezależnych transakcjach. Sprawdź rysunek 1, Jak to zrobić. Możesz przeczytać więcej o arkuszach nie udostępnionych dla programistów SQL w tym poprzednim poście.

SQL Developer nie udostępniony arkusz roboczy

Rysunek 1 – Otwarcie nowego nie udostępnionego arkusza roboczego.

teraz pierwszą rzeczą, którą zrobimy, jest wykonanie regularnego wyboru w obu arkuszach roboczych. Wykonamy select, aby uzyskać rekord, w którym WorkerID jest równy 1. Nie wykonuj żadnych zatwierdzeń ani wycofań, po prostu wykonaj to samo zapytanie w obu arkuszach roboczych.

select * from worker where WorkerID = 1;

zgodnie z oczekiwaniami, nie ma problemu ze współbieżnością i otrzymamy rekord w obu transakcjach (z nazwą roboczą równą „John”).

teraz wrócimy do pierwszego arkusza roboczego (tego samego, w którym utworzyliśmy tabelę) i dodamy klauzulę „do aktualizacji” na końcu instrukcji select, jak wskazano poniżej. Ponownie, nie rób żadnych commitów ani wycofywania.

select * from worker where WorkerID = 1 for update;

kiedy to robimy, blokujemy rekordy zbioru wyników, bez potrzeby ich aktualizacji . Innymi słowy, wyraźnie blokujemy zapisy. Oczywiście, że kiedy je zamkniemy, możemy je zaktualizować, jeśli chcemy. Blokady na płytach są uwalniane, gdy robimy następny commit lub rollback .

tak więc, aby sprawdzić, czy blokady działają, przechodzimy teraz do drugiego arkusza roboczego (nie udostępnionego arkusza roboczego, który otworzyliśmy). Tam, jeśli wykonamy zwykły select, bez „for update sentence”, dostaniemy rekord bez żadnego problemu.

select * from worker where WorkerID = 1;

ale wtedy, jeśli powtórzymy select, teraz ze zdaniem” do aktualizacji ” na końcu, zawiesi się, ponieważ inna transakcja ma zablokowany rekord z WorkerID równy 1 i próbujemy go ponownie zablokować.

select * from worker where WorkerID = 1 for update;

aby go odblokować, po prostu wróć do pierwszego arkusza roboczego i zatwierdź lub wycofaj transakcję. Teraz wróć do nie udostępnionego arkusza roboczego, a polecenie SQL powinno zostać wykonane, zwracając żądany rekord.

blokowanie różnych rekordów

jedną ważną rzeczą, o której należy pamiętać, jest to, że tylko rekordy, które są częścią zestawu wyników, są blokowane przez transakcję. Tak więc różne transakcje mogą wykonać „wybierz do aktualizacji” w różnych rekordach.

aby to przetestować, przejdź do pierwszego arkusza roboczego i wybierz zarówno rekord 1, jak i 3, z następującym zdaniem wybierz:

select * from worker where WorkerID = 1 or WorkerID = 3 for update;

teraz przejdź do nie udostępnionego arkusza roboczego i spróbuj zablokować rekord 2.

select * from worker where WorkerID = 2 for update;

powinno zadziałać i zwrócić wynik, ponieważ rekord z WorkerID równy 2 nie został zablokowany przez pierwszą transakcję. Teraz, jeśli w tym samym nie udostępnionym arkuszu roboczym spróbujemy zablokować rekord o ID pracownika równym 1 lub rekord o ID pracownika równym 3 (lub obu), zawiesi się, dopóki nie zatwierdzimy lub wycofamy transakcji z pierwszego arkusza roboczego.

powiązane treści

  • Oracle Select for update statment

Write a Comment

Twój adres e-mail nie zostanie opublikowany.