2009-10-15 18 views
7

Czy istnieje sposób, aby sprawdzić, czy wiersz został zablokowany do aktualizacji w Oracle?Jak sprawdzić, czy wiersz jest zablokowany do aktualizacji?

Jako przykład, załóżmy następujące zapytanie, wykonywaną przez jednego użytkownika:

select * from SOME_TABLE where THE_ID = 1000 for update; 

z innym użytkownikiem Chcę sprawdzić, jeśli wiersz z THE_ID = 1000 jest zablokowana. Jeśli spróbuję aktualizacji lub czegoś, co drugi użytkownik zostanie zablokowany i nadal czeka (nie chcę tego).

Próbowałem również uruchomione następujące kwerendy z drugim użytkownikiem:

select * from SOME_TABLE where THE_ID = 1000 for update NOWAIT; 

Ponieważ nie mogę umieścić dwa zamki w tym samym rzędzie będzie to niepowodzeniem. I tak. Otrzymuję "ORA-00054: zasób zajęty i pozyskany z określonym błędem NOWAIT". Czy zawsze mogę liczyć na ten błąd, aby sprawdzić obecność blokady lub czy istnieje prostszy i bardziej przejrzysty sposób określania, czy wiersz jest zablokowany?

Dziękujemy!

+1

powinieneś otrzymasz ten błąd "ORA-00054: zasoby zajęte i nabyte z NOWAIT określona" - czy jesteś pewien, że twój użytkownik może zobaczyć tabelę? – SeriousCallersOnly

+0

@ SeriousCallersOnly: Dzięki, rzeczywiście mam "ORA-00054: zasób zajęty i pozyskany z błędem określonym przez NOWAIT". ORA-00942 został rzucony przez kolejną warstwę mojej aplikacji. Przepraszam za to. Będę edytować pytanie. –

Odpowiedz

14

Można napisać procedurę z FOR UPDATE nowait i zwróci komunikat o błędzie, gdy rząd jest zablokowany

SQL> CREATE OR REPLACE PROCEDURE do_something(p_id NUMBER) IS 
    2  row_locked EXCEPTION; 
    3  PRAGMA EXCEPTION_INIT(row_locked, -54); 
    4 BEGIN 
    5  FOR cc IN (SELECT * 
    6     FROM some_table 
    7     WHERE ID = p_id FOR UPDATE NOWAIT) LOOP 
    8  -- proceed with what you want to do; 
    9  NULL; 
10  END LOOP; 
11 EXCEPTION 
12  WHEN row_locked THEN 
13  raise_application_error(-20001, 'this row is locked...'); 
14 END do_something; 
15/

Procedure created 

Teraz zbudujmy mały przykład z dwóch sesji:

session_1> select id from some_table where id = 1 for update; 

     ID 
---------- 
     1 

session_2> exec do_something(1); 

begin do_something(1); end; 

ORA-20001: this row is locked... 
ORA-06512: at "VNZ.DO_SOMETHING", line 11 
ORA-06512: at line 2 

session_1> commit; 

Commit complete 

session_2> exec do_something(1); 

PL/SQL procedure successfully completed 
+0

Jak już odpowiedziałem na SeriousCallersOnly, rzeczywiście mam błąd ORA-00054. Dziękuję Ci. Ale czy mogę na to liczyć, żeby sprawdzić zamek? –

+0

@dpb: możesz polegać na tym mechanizmie. Dodałem mały przykład pokazujący, jak procedura działałaby z dwiema sesjami blokującymi ten sam wiersz. –

1

Nie jest ani prosty ani czysty, ale informacje są dostępne w widokach i V$SESSION.

Jednakże, jeśli czujesz potrzebę użycia czegoś takiego w ramach normalnego kodu aplikacji, musisz pomyśleć jeszcze raz. Aplikacje nie powinny przejmować się sposobem blokowania bazy danych. Jeśli masz do czynienia z zakleszczeniami, musisz zrestrukturyzować swoje zapytania, aby się nie pojawiły.

Powiązane problemy