2009-09-23 10 views
8

to czuje się jak głupie pytanie, ale widzę, co następuje w Oracle koncepcji przewodnika dotyczącego zarządzania transakcjami:Czy Oracle wycofuje transakcję z powodu błędu?

Transakcja kończy się, gdy którykolwiek z następujących zdarzeń:

Użytkownik wydaje COMMIT lub ROLLBACK oświadczenie bez klauzuli SAVEPOINT.

Użytkownik uruchamia instrukcję DDL, taką jak CREATE, DROP, RENAME lub ALTER. Jeśli bieżąca transakcja zawiera jakiekolwiek instrukcje DML , Oracle najpierw zatwierdza transakcję , a następnie uruchamia i zatwierdza instrukcję DDL jako nową, pojedynczą transakcję wyciągu .

Użytkownik rozłącza się z Oracle. Bieżąca transakcja jest zatwierdzona.

Proces użytkownika kończy się nienormalnie. Bieżąca transakcja jest wycofana wstecz.

Czy interpretować ostatni punkt oznacza, że ​​jeśli wydam zapytanie, które zawiera błąd, transakcja zostanie wycofana?

+0

Właściwie to brzmi jak bardzo interesujące pytanie do mnie. Postgres wycofuje się przy błędzie i często uważałem to za denerwujące (i zastanawiałem się, czy Oracle zrobił coś podobnego). – jsight

+0

Powiedz, dlaczego korzystasz z transakcji, jeśli nie chcesz wycofywać błędów? Jest to jeden z głównych celów transakcji. –

+0

@Oliver: Niekoniecznie chcę lub nie chcę ich. Chcę tylko wiedzieć, jak działają. –

Odpowiedz

7

"Proces użytkownika" w tym kontekście odnosi się do procesu uruchomionego na komputerze klienta, który tworzy połączenie z Oracle. Innymi słowy, jeśli korzystasz z aplikacji A (SQL*Plus, TOAD itp.) W celu nawiązania połączenia z Oracle, proces użytkownika to SQL*Plus, TOAD itd. Jeśli ten proces użytkownika umrze, gdy byłeś w trakcie transakcji, ta transakcja zostanie wycofany. Stanie się tak, gdy tylko PMON odkryje, że klient zginął, co może zająć trochę czasu - Oracle nie zawsze jest w stanie odróżnić niepowodzenie procesu użytkownika od procesu użytkownika, który po prostu nie wydaje komend chwila.

1

Zgadzam się z Justinem, jego wgląd jest poprawny. Dodawanie dodatkowych informacji: jako programista aplikacji powinieneś jawnie wywołać komendę wycofania, jeśli wystąpią błędy. Oznacza to, że powinieneś również rozważyć grupowanie wyciągów w bloki transakcyjne. Bloki transakcyjne i wycofywanie zmian są różnie obsługiwane za pomocą różnych technologii, warto przeprowadzić pewne badania, aby upewnić się, że dobrze je rozumiesz.

12

to interesujące pytanie!

Gdy Oracle napotka błąd, wycofa bieżące oświadczenie , a nie transakcję. Instrukcja jest instrukcją najwyższego poziomu, może to być instrukcja SQL (INSERT, UPDATE ...) lub blok PL/SQL.

Oznacza to, że gdy instrukcja (na przykład procedura pl/sql wywoływana z języka Java) zwróci błąd, Oracle umieści transakcję w tym samym stanie logicznym, co przed wywołaniem. Jest to niezmiernie pomocne, nie musisz się martwić o wykonane w połowie procedury (**).

This thread on AskTom covers the same topic:

[pismo] albo całkowicie się dzieje lub jej całkowicie nie zdarza i sposób że działa to baza danych ma logiczny odpowiednik:

begin 
    savepoint foo; 
    <<your statement>> 
exception 
    when others then rollback to foo; 
        RAISE; 
end; 

This funkcja, moim zdaniem, dlatego jest o wiele łatwiejsze do napisania kodu bazy danych (*) w pl/sql niż w jakimkolwiek innym języku.

(*) kod, który współdziała z bazą Oracle oczywiście, przypuszczam, że rodzime języki proceduralne innych DBMS mają podobne funkcje.

(**) Dotyczy to wyłącznie DML od DDL are not transactional w Oracle. Należy również zachować ostrożność w przypadku niektórych pakietów DBMS, które aktualizują słownik danych (takich jak DBMS_STATS), często dokonują zmian podobnych do DDL i zatwierdzają wydania. Jeśli masz wątpliwości, zapoznaj się z documentation.

Aktualizacja: to zachowanie jest jednym z najważniejszych koncepcji w PL/SQL, ja dostarczy mały przykład w celu wykazania niepodzielność z PL/SQL:

SQL> CREATE TABLE T (a NUMBER); 

Table created 

SQL> CREATE OR REPLACE PROCEDURE p1 AS 
    2 BEGIN 
    3  -- this statement is successful 
    4  INSERT INTO t VALUES (2); 
    5  -- this statement will raise an error 
    6  raise_application_error(-20001, 'foo'); 
    7 END p1; 
    8/

Procedure created 

SQL> INSERT INTO t VALUES (1); 

1 row inserted 

SQL> EXEC p1; 

begin p1; end; 

ORA-20001: foo 
ORA-06512: at "VNZ.P1", line 5 
ORA-06512: at line 2 

SQL> SELECT * FROM t; 

     A 
---------- 
     1 

Oracle wycofał transakcję do punktu tuż przed wywołaniem p1. Nie ma pół-pracy. To tak, jakby procedura p1 nigdy nie została wywołana.

+1

Mylisz się co do instrukcji i bloków PL/SQL. Blok PL/SQL nie jest instrukcją niż INSERT, UPDATE lub DELETE. Jeśli blok PL/SQL zgłasza błąd i nie ma obsługi punktu zachowywania, tak jak twój fragment kodu, musisz martwić się o połowy wykonane procedury. – Christian13467

+2

Chrześcijanin, to źle. Jeśli wyjątek jest wywoływany przez blok PL/SQL najwyższego poziomu, tak jak wywoływany jest przez klienta, następuje wycofanie do punktu przed wywołaniem tego bloku (zakładając, że nie było żadnego zatwierdzenia w interweniującym PL/SQL). –

+0

@Christian: Zaktualizowałem swoją odpowiedź, mam nadzieję, że to wyjaśni koncepcję, którą próbowałem wyjaśnić. –

Powiązane problemy