Blog > Komentarze do wpisu
Bezstanowe pakiety (stateless packages) - ORA-04068
Dziś nawiąże do jednego z moich ostatnich postów, który z perspektywy moich ostatnich ustaleń, wydaje się być nieco niepełny i nieścisły. Wczoraj mianowicie, zorientowałem się, co tak naprawdę jest głównym powodem błędów: ORA-04068.

 

>>> ZACZYNAMY <<<

 

Dziś nawiąże do jednego z moich ostatnich postów, który z perspektywy moich ostatnich ustaleń, wydaje się być nieco niepełny i nieścisły.

Wczoraj mianowicie, zorientowałem się, co tak naprawdę jest głównym powodem poniższego błędu: 


ORA-04068

 

ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package "TMP_TEST" has been invalidated
ORA-04065: not executed, altered or dropped package "TMP_TEST"
ORA-06508: PL/SQL: could not find program unit being called: "TMP_TEST"
ORA-06512: at line 1


Jest to wykorzystanie w pakietach zmiennych (package level variables). Wykorzystanie takowych (deklaracja stałych na tym samym poziomie prowadzi do identycznych problemów) powoduje zmianę stanu pakietu przy każdej rekompilacji, co w rezultacie prowadzi do powyższego błędu.

Zademonstruje to na przykładzie.  W pierwszej sesji stwórzmy prosty pakiet:


CREATE OR REPLACE PACKAGE TMP_TEST
IS
   PROCEDURE p_foo;
END TMP_TEST;
/

 

CREATE OR REPLACE PACKAGE BODY TMP_TEST
IS

   PROCEDURE p_foo
   IS
      i   NUMBER;
   BEGIN
      FOR i IN 1 .. 10
      LOOP
         DBMS_OUTPUT.PUT_LINE ('i = ' || TO_CHAR (i));
         DBMS_LOCK.SLEEP (1);
      END LOOP;
   END;

END TMP_TEST;
/


W sesji drugiej wywołajmy naszą procedurę p_foo:

 

EXEC TMP_TEST.P_FOO;

 

Bufor wyświetli spodziewane dane:

 

i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 10


Jeśli wrócimy do sesji pierwszej i skompilujemy ponownie nasz pakiet, ponowne wykonanie procedury zakończy się również sukcesem.

Teraz zmieńmy naszą specyfikację na poniższą:


CREATE OR REPLACE PACKAGE TMP_TEST
IS
   vn_number   NUMBER;   

   PROCEDURE p_foo;

END TMP_TEST;
/

 

Teraz wykonanie procedury w sesji drugiej powinno zakończyć się... również sukcesem (może wydać się to nieco nieintuicyjne) i znów w buforze zobaczymy spodziewane wyniki.



Skompilujmy naszą specyfikację po raz kolejny. Wywołanie procedury tym razem zakończy się niepowodzeniem i wyświetlony zostanie poniższy błąd:


ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package "TMP_TEST" has been invalidated
ORA-04065: not executed, altered or dropped package " TMP_TEST"
ORA-06508: PL/SQL: could not find program unit being called: "TMP_TEST"
ORA-06512: at line 1

Ma to oczywiście sens. Oracle nie ma pojęcia jak i gdzie używana jest nasza zmienna, nie wie, jaką miała wartość i to właśnie to powoduje zmianę stanu naszego pakietu.

Rozwiązaniem wszystkich problemów ;) wydaję się więc być unikanie zmiennych na poziomie pakietów (nie ma znaczenia czy będzie to specyfikacja czy ciało).

W naszym kodzie zmiennych/stałych takich mamy sporo, czasami ciężko jest ich uniknąć (dotychczas też nie zdawaliśmy sobie sprawy, do jakich problemów prowadzą). Zmieniamy jednak podejście i będziemy sukcesywnie przenosić, co tylko możliwe do jednego pakietu (bądź dwóch), w których będą tylko zmienne/stałe np.: COMMON_CONSTANTS.

Do sprawy najprawdopodobniej jeszcze powrócę. Badam właśnie możliwości oferowane przez Oracla i pozwalające na zaatakowanie problemu z innej strony. Jeśli ktoś chce podłubać sam proszę poszukać informacji na temat procedur RESET_PACKAGE i MODIFY_PACKAGE_STATE z pakietu DBMS_SESSION oraz o dyrektywie SERIALLY_REUSABLE.

Do następnego razu.


piątek, 14 października 2011, m0rt1m3r
Tagi: pl/sql oracle

Related Posts Plugin for WordPress, Blogger...

Polecane wpisy

Komentarze
Gość: killserv, 85.182.240.*
2011/10/25 15:48:15
hi
dopiero teraz widze ten twoj wpis...
cos mi google.reader szwankuje!
i co znalazles cos?
bys skrobnal maila z info
mam malo czasu ale to dla mnie tez wazny temat

pozdro
-
2011/10/26 07:57:54
Z trzech wspomnianych SERIALLY_REUSABLE wydaje sie byc najlepszym rozwiazaniem, przynajmniej tak jest w moim wypadku. Pragma ta znaczy tyle ze stan pakiety jest wazny podczas jednego tylko wywolania np. procedury, po ktorym pamiec wykorzystana przez stale/zmienne moze byc wykorzystana ponownie. Wada jest to, ze pakiety oznaczone jako SERIALLY_REUSABLE nie moga byc wykorzystywane w triggerach ani w zapytaniach SQL. Jesli chcesz z niej skorzystac to i specyfikacja i cialo pakietu musi byc ta pragma.
W weekend postaram sie cos jedzcze dodac.




PowerBuilder Tetris
D - Tetris



Programowanie iOS

C# ToolBox

SQL / TSQL / PLSQL ToolBox

Linux / Unix ToolBox





Zaprzyjaznione Strony

Sprite Bandits

Cake Time