در دیتابیس اوراکل، state بستههای PL/SQL در سطح session حفظ می شود. یعنی زمانی که یک package در session ای اجرا میشود، متغیرهای global آن، مقادیر خود را در میان چندین فراخوانی حفظ میکنند. در نسخههای قبلی Oracle(قبل از 26ai)، زمانی که یک package دوباره compile میشد، تمام sessionهایی که state آن package را نگه داشته اند با خطاهای ORA-04068 مواجه میشدند.
در اوراکل 26ai، عبارت RESETTABLE راهی جدید برای مدیریت state بستههای PL/SQL معرفی میکند. با استفاده از این عبارت، زمانی که package تشخیص دهد وضعیت آن دیگر معتبر نیست، بهصورت خودکار reset میشود، و مانع از کرش کردن session می شود. برای درک بهتر عملکرد آن، سناریوی عملی زیر را بررسی میکنیم.
1.رفتار پیشفرض package (بدون استفاده از RESETTABLE)
ابتدا یک package ساده همراه با یک متغیر global و یک procedure که مقدار متغیر را در هر اجرا یک عدد افزایش می دهد را ایجاد میکنیم.
CREATE OR REPLACE PACKAGE my_pkg AS
Glob_cnt number := 0;
PROCEDURE prc_inc_cnt;
END my_pkg;
/
Package created
CREATE OR REPLACE PACKAGE BODY my_pkg AS
PROCEDURE prc_inc_cnt IS
BEGIN
Glob_cnt := Glob_cnt + 1;
DBMS_OUTPUT.PUT_LINE('Counter = ' || Glob_cnt);
END;
END my_pkg;
/
Package body created
اکنون رفتار آن را در دو session مختلف بررسی میکنیم.
Session 1:
SQL> set serveroutput on SQL> exec my_pkg.prc_inc_cnt; Counter = 1 SQL> exec my_pkg.prc_inc_cnt; Counter = 2
Session 2:
SQL> alter package my_pkg compile; Package altered
Session 1:
SQL> exec my_pkg.prc_inc_cnt; ORA-04068: existing state of packages has been discarded ORA-04061: existing state of package "VAHID.MY_PKG" has been invalidated ORA-04065: not executed, altered or dropped package "VAHID.MY_PKG" ORA-06508: PL/SQL: could not find program unit being called: "VAHID.MY_PKG" ORA-06512: at line 1
در اینجا، session با خطا مواجه میشود زیرا دیتابیس به هنگام recompile شدن package در session 2، وضعیت آن را در session 1 حذف میکند. فراخوانی بعدی باعث میشود package دوباره مقداردهی اولیه شود:
SQL> set serveroutput on SQL> exec my_pkg.prc_inc_cnt; Counter = 1 SQL> exec my_pkg.prc_inc_cnt; Counter = 2
2. استفاده از عبارت RESETTABLE
حال package را تغییر میدهیم تا از عبارت RESETTABLE استفاده کنیم. این عبارت باید مستقیماً در دستور CREATE PACKAGE استفاده شود:
CREATE OR REPLACE PACKAGE my_pkg RESETTABLE AS
Glob_cnt number := 0;
PROCEDURE prc_inc_cnt;
END my_pkg;
/
Package created
CREATE OR REPLACE PACKAGE BODY my_pkg RESETTABLE AS
PROCEDURE prc_inc_cnt IS
BEGIN
Glob_cnt := Glob_cnt + 1;
DBMS_OUTPUT.PUT_LINE('Counter = ' || Glob_cnt);
END;
END my_pkg;
/
Package body created
در ادامه همان سناریو را تکرار میکنیم تا ببینیم رفتار package با استفاده از RESETTABLE چگونه متفاوت است.
Session 1:
SQL> set serveroutput on SQL> exec my_pkg.prc_inc_cnt; Counter = 1 SQL> exec my_pkg.prc_inc_cnt; Counter = 2
Session 2:
SQL> ALTER PACKAGE my_pkg COMPILE; Package altered
Session 1:
SQL> exec my_pkg.prc_inc_cnt; Counter = 1 SQL> exec my_pkg.prc_inc_cnt; Counter = 2
در این حالت دیگر خطای ORA-04068 مشاهده نمیشود و مقدار متغیر به صورت خودکار reset شده است.