Benutzer-Werkzeuge

Webseiten-Werkzeuge


prog:plsql_sleep_19c

PL/SQL - Eine DB Session "schlafen" legen - Wie und welche Sleep Funktion einsetzen?

Aufgabe: Eine Datenbank Session soll mit einer sleep Funktion eine gewisse Zeit pausiert werden.

Z.B. in einem Monitoring Job, der jede Minute prüfen ob ein andere Job noch aktiv ist und keine Fehler geworfen hat.

Möglichkeiten:

APEX Installiert:

  • APEX_UTIL.pause ( aber nur bis maximal 120 Sekunden! , Wait Event „PL/SQL lock timer“)

DB Version vor 18c:

  • Java über java.lang.Thread.sleep ( Waits Events in der Statistik sichtbar, nicht verwirren lassen!)
  • DBMS_LOCK.sleep (Sicherheitsproblem mit generellen Zugriff auf das Package DBMS_LOCK, Wait Event „PL/SQL lock timer“))

DB Version ab 18c

  • DBMS_SESSION.sleep ( so sollte es schon immer sein … )

APEX_UTIL.pause

Ist in der DB APEX installiert, kann auf APEX_UTIL zurückgegriffen werden.

10 Sekunden warten:

BEGIN
 APEX_UTIL.PAUSE(10);
END;
/

Jetzt ist nur die Frage, wie das intern umgesetzt wird. Das Synonym „APEX_UTIL“ zeigt jedenfalls auf das Package „htmldb_util“ und von da auf „WWV_FLOW_UTILITIES.PAUSE“, dort wird dann „SYS.DBMS_LOCK.SLEEP(L_SECONDS);“ gekapselt.

Und alle Werte über 120 Sekunden werden mit dem Default 120 Sekunden überschrieben!

D.h. die maximale Wartezeit beträgt 120 Sekunden.

Eigene Routine um auch länger als 120s warten zu können und dann ab der Version 18 gleich DBMS_SESSION.sleep verwenden zu können:

-- 
CREATE OR REPLACE 
PROCEDURE sleep_plsql(p_seconds IN NUMBER)
IS
  v_120Parts pls_integer;
  v_LastRound pls_integer;
BEGIN
   -- if we are on 18 use the DBMS_SESSION sleep methode!
   $IF DBMS_DB_VERSION.VER_LE_12 $THEN
 
          -- we need an oracle apex security context .-(
          -- put in your workspace
          apex_util.set_security_group_id (p_security_group_id => apex_util.find_security_group_id (p_workspace => 'DME'));
          -- 
          IF p_seconds/120 > 1 THEN
              --- floor largest integer equal to or less than
              v_120Parts:=FLOOR(p_seconds/120);
              -- return the remainder 
              v_LastRound:=MOD( p_seconds, 120 );
          ELSE
              v_120Parts:=0;
              v_LastRound:=p_seconds;
          END IF;
 
          --  APEX_UTIL.PAUS cann only sleep may 120s!
          -- 
          IF v_120Parts > 0 THEN
              FOR i IN 1..v_120Parts
               loop
                 APEX_UTIL.PAUSE(120);
               END loop;
           END IF;
           ---
           IF v_LastRound > 0 THEN
              APEX_UTIL.PAUSE(v_LastRound);
           END IF; 
    $ELSE
         DBMS_SESSION.sleep(p_seconds);
    $END
END;
 
--- testen
 
SET serveroutput ON
BEGIN
dbms_output.put_line('-- Info start at '||to_char(systimestamp,'hh24:mi:SSxFF'));
sleep_plsql(11);
dbms_output.put_line('-- Info start at '||to_char(systimestamp,'hh24:mi:SSxFF'));
sleep_plsql(119);
dbms_output.put_line('-- Info start at '||to_char(systimestamp,'hh24:mi:SSxFF'));
sleep_plsql(123);
dbms_output.put_line('-- Info start at '||to_char(systimestamp,'hh24:mi:SSxFF'));
sleep_plsql(245);
dbms_output.put_line('-- Info start at '||to_char(systimestamp,'hh24:mi:SSxFF'));
sleep_plsql(545);
dbms_output.put_line('-- Info start at '||to_char(systimestamp,'hh24:mi:SSxFF'));
END;
/

Problem ORA-20987: APEX - Package variable g_security_group_id must be set

Fehler:

ORA-20987: APEX - Package variable g_security_group_id must be SET. - Contact your application administrator.

Lösung, Security ID setzen!

  -- we need an oracle apex security context .-(
  -- put in your workspace
 
  apex_util.set_security_group_id (p_security_group_id => apex_util.find_security_group_id (p_workspace => 'GPI'));
 

Das ist dann leider nicht so schön, damit wird der Code doch sehr von der Umgebung abhängig.

Wait Event - PL/SQL lock timer

In der DB ist „PL/SQL lock timer“ der Wait Event hinter diesem Aufruf in den Wait Statistiken.


Java

Verwendung der Java Klasse „java.lang.Thread“

CREATE OR REPLACE PROCEDURE sleep_java(p_milli_seconds IN NUMBER) 
  AS 
  LANGUAGE JAVA NAME 'java.lang.Thread.sleep(long)';

Nachteil: In den AWR / Statspack Berichten wird dann OVJM gerne als häufigster Wait aufgezeigt, sind noch andere Java Komponenten im Einsatz verfälscht das stark das Ergebniss.

Wie:  OVJM Waits mit java.lang.Thread.sleep in der Datenbank


DBMS_LOCK.sleep

Nachteil:

  • Sicherheitsprobleme mit DBMS_LOCK habe dazu geführt das her keine Public Synonym in der DB für dieses Package vorliegt und damit ein direkter Grant benötigt wird!

Ab 18c auf keine Fall mehr verwenden! Gar nicht mehr offiziell in der Doku!


DBMS_SESSION.sleep

Ab der Version 18c!

Session „schläft“ für n Sekunden, der Maximal Wert beträgt 3600 Sekunden (ansonsten gibt es ein ORA-38148: invalid time limit specified!)

BEGIN
 dbms_session.sleep(10);
END;

Quellen

Cookies helfen bei der Bereitstellung von Inhalten. Diese Website verwendet Cookies. Mit der Nutzung der Website erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Computer gespeichert werden. Außerdem bestätigen Sie, dass Sie unsere Datenschutzerklärung gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website. Weitere Information
"Autor: Gunther Pipperr"
prog/plsql_sleep_19c.txt · Zuletzt geändert: 2021/02/22 16:16 von gpipperr