Blog programisty w Oracle PL/SQL

Jest to blog eksperymentatora programisty w PL/SQL dla Oracle. Wszystkie kody tutaj zamieszczone mogą być dowolnie wykorzystywane i zmieniane. A jeśli Ktoś z Gości znajdzie błąd, będę niezwykle wdzięczny...
Zapisz

Szukaj na tym blogu

niedziela, 19 lutego 2012

Kiedy serwer śpi

Istotnym problemem jest wykrywanie obciążenia na serwerach bazodanowych i szukanie dziur czasowych na uruchomienie dodatkowych funkcjonalności. Niektóre moje funkcjonalności  nie mają kluczowego znaczenia, natomiast nie powinny być uruchamianie, kiedy instrukcja top pokazuje pełne wykorzystanie zasobów serwera.. W tym celu napisałem sobie funkcję zwracającą wartość IDLE z  polecenia top.  funkcja działa poprawnie na serwerach jedno i wieloprocesorowych dla pojedyńczej instancji danej bazy, nie była testowana w konfiguracjach  wieloinstancyjnych z przełączaniem.. Rozbieżnośc między top a poniższą funkcją była mniejsza niż 8 %...

CREATE OR REPLACE FUNCTION  Fdb_GetIdlePercent(pn_Seconds NUMBER DEFAULT 5) RETURN NUMBER
AS
 vn_IdleTime    NUMBER;
 vn_CPUCount NUMBER;BEGIN
    SELECT VALUE INTO vn_IdleTime FROM V$OSSTAT WHERE STAT_NAME = 'IDLE_TIME';
    SELECT VALUE INTO vn_CPUCount FROM V$OSSTAT WHERE STAT_NAME = 'NUM_CPUS';
    SYS.DBMS_LOCK.SLEEP( pn_Seconds);
  SELECT VALUE - vn_IdleTime    INTO vn_IdleTime FROM V$OSSTAT WHERE STAT_NAME = 'IDLE_TIME';  
    RETURN ROUND(vn_IdleTime/(vn_CPUCount *pn_Seconds*100)  *100, 2 );   
    EXCEPTION WHEN OTHERS THEN
           RETURN 100;
END;

Funkcja wymaga następujących niestandardowych uprawnień:
GRANT EXECUTE ON   SYS.DBMS_LOCK TO :current_user;
GRANT SELECT ON SYS.V$OSSTAT TO :current_user;

Istotnym parametrem jest czas pomiaru - 5 sekund lub dłużej powinno wystarczyć..

 Poniższy  blok czeka, aż parametr idle spadnie do 50% na podstawie  sprawdzania przedziałów czasowych o długości 300 sekund.
DECLARE
      vn_Idle NUMBER;
      vn_Delay NUMBER :=  300;
BEGIN
    LOOP
         vn_Idle := Fdb_GetIdlePercent(vn_Delay);
         EXIT WHEN vn_Idle <= 50;
    END LOOP; 
--- Insert your code here 
END;