sobota, 21 grudnia 2013

Klauzula FOR UPDATE

Przy użyciu klauzuli FOR UPDATE możemy zablokować wiersze do edycji przez inne sesje. Działa to na zasadzie transakcyjnej blokady zasobów. Jeśli my wykonamy jakiś UPDATE lub DELETE, wiersze których te polecenia zostaną zablokowane do czasu zatwierdzenia lub wycofania transakcji. W tym czasie inne sesje usiłujące dokonać jakiejkolwiek zmiany będą musiały oczekiwać na zwolnienie zasobów przez nas. Najniższy poziom blokady to wiersz, tak więc nawet jeśli zmienimy zawartość jednej kolumny, nikt nie będzie mógł zmienić również pozostałych kolumn w tych wierszach.
Klauzulę tę możemy wykorzystywać zarówno w SQL, jak i w kursorach w PL/SQL. Przykład użycia w SQL:






Wyświetlam 3 osoby z departamentu nr 90 , jednocześnie blokując te wiersze do edycji przez inne sesje. Teraz z innej sesji usiłuję te wiersze zmodyfikować:



Zauważ że modyfikuję inną kolumnę, niż te które wyświetlałem z pierwszej sesji. Sesja czeka na zwolnienie zasobów. Możemy teraz swobodnie dokonać zmian, bez obawy że ktoś inny w międzyczasie dokona jakichś zmian na „naszych” wierszach.


Dopiero po wydaniu polecenia „COMMIT”, wiersze zostają odblokowane i sesja która oczekiwała na odblokowanie zasobów może dokonać zmian:





Klauzulę FOR UPDATE możemy wykorzystywać również w PL/SQL w kursorach. Samo zadeklarowanie kursora nie spowoduje jednak blokady wierszy, jak się za chwilę przekonamy.
Uruchomiłem blok anonimowy z samą deklaracją kursora:


Aktualizacja z innej sesji przebiegła bez żadnych problemów:





Aby wiersze zostały zablokowane , kursor trzeba przynajmniej otworzyć:



Nie koniecznie musi to być otwarcie jawne, może być to również automatyczne otwarcie kursora które
następuje w pętli kursorowej, tak jak to widać poniżej:




Z wykorzystaniem klauzuli for update wiąże się również klauzula „WHERE CURRENT OF” która pozwala aktualizować lub kasować wiersze zablokowane przez kursor.



Istotna uwaga: klauzula WHERE CURRENT OF odnosi się do wiersza który właśnie został zfetchowany z kursora.

Niezależnie od ilości wierszy w kursorze, klauzula WHERE CURRENT OF odnosi się do ostatnio pobranego z kursora wiersza. Poniżej zastosowałem pętle kursorową, i jak widzimy zawsze ilość zaktualizowanych wierszy wynosi 1.






W przypadku próby wykorzystania klauzuli WHERE CURRENT OF bez uprzedniego fetcha, dostajemy błąd :





2 komentarze:

  1. Używając klauzuli FOR UPDATE w kursorach, aby zablokować zasób trzeba kursor otworzyć, czy zamknięcie go powoduje zwolnienie zasobu? Czy trzeba jeszcze użyć polecenia COMMIT?

    OdpowiedzUsuń