Benutzer-Werkzeuge

Webseiten-Werkzeuge


prog:plsql_sleep_19c

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
prog:plsql_sleep_19c [2021/02/19 09:23] – [PL/SQL - Eine DB Session "schlafen" legen - Wie und welche Sleep Funktion einsetzen?] gpipperrprog:plsql_sleep_19c [2023/02/01 12:12] (aktuell) – [DBMS_SESSION.sleep] gpipperr
Zeile 1: Zeile 1:
-=====PL/SQL - Eine DB Session "schlafen" legen - Wie und welche Sleep Funktion einsetzen? =====+=====PL/SQL - Eine DB Session "schlafen" legen - Wie und welche Sleep Funktion in welcher Oracle DB Version einsetzen? =====
  
  
-Aufgabe: Eine Datenbank Session soll mit einer sleep Funktion eine gewisse Zeit pausiert werden.+**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.  Z.B. in einem Monitoring Job, der jede Minute prüfen ob ein andere Job noch aktiv ist und keine Fehler geworfen hat. 
 +
 +<note warning>DBMS_LOCK.sleep - ab 18c bzw. in 19c / 23c auf keine Fall mehr verwenden! Gar nicht mehr offiziell in der Doku!</note>
  
  
Zeile 11: Zeile 13:
  
 **APEX Installiert:** **APEX Installiert:**
-  * APEX_UTIL.pause+  * APEX_UTIL.pause ( aber <fc #800000>nur bis maximal 120 Sekunden!</fc> , Wait Event "PL/SQL lock timer"
  
 **DB Version vor 18c:** **DB Version vor 18c:**
-  * Java über java.lang.Thread.sleep +  * Java über java.lang.Thread.sleep  ( <fc #800000>Waits Events in der Statistik</fc> sichtbar, nicht verwirren lassen!) 
-  * DBMS_LOCK.sleep+  * DBMS_LOCK.sleep (<fc #800000>Sicherheitsproblem</fc> mit generellen Zugriff auf das Package DBMS_LOCK, Wait Event "PL/SQL lock timer"))
  
  
 **DB Version ab 18c** **DB Version ab 18c**
-  * DBMS_SESSION.sleep+  * <fc #008080>**DBMS_SESSION.sleep**</fc>  ( <fc #008000>so sollte es schon immer sein ...</fc> )  
  
  
Zeile 39: Zeile 42:
 </code> </code>
  
 +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:
 +<code sql>
 +-- 
 +CREATE OR REPLACE 
 +PROCEDURE sleep_plsql(p_seconds IN NUMBER)
 +IS
 +  v_parts pls_integer;
 +  v_LastRound pls_integer;
 +  v_max_pos_seconds pls_integer:=120;
 +BEGIN
 +
 +
 +  $IF DBMS_DB_VERSION.VER_LE_12 $THEN
 +  v_max_pos_seconds:=120;
 +  $ELSE
 +    v_max_pos_seconds:=3600;
 +  $END
 +  
 +   IF p_seconds/v_max_pos_seconds > 1 THEN
 +      --- floor largest integer equal to or less than
 +      v_parts:=FLOOR(p_seconds/v_max_pos_seconds);
 +      -- return the remainder 
 +      v_LastRound:=MOD( p_seconds, v_max_pos_seconds );
 +   ELSE
 +      v_parts:=0;
 +      v_LastRound:=p_seconds;
 +   END IF;
 +
 +
 +   -- 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 => 'GPI'));
 +         
 +          --  APEX_UTIL.PAUS cann only sleep may 120s!
 +          -- 
 +          IF v_parts > 0 THEN
 +              FOR i IN 1..v_parts
 +               loop
 +                 APEX_UTIL.PAUSE(120);
 +               END loop;
 +           END IF;
 +           ---
 +           IF v_LastRound > 0 THEN
 +              APEX_UTIL.PAUSE(v_LastRound);
 +           END IF; 
 +    $ELSE  
 +          --  DBMS_SESSION can only sleep may 3600s!
 +          -- 
 +          IF v_parts > 0 THEN
 +              FOR i IN 1..v_parts
 +               loop
 +                 DBMS_SESSION.sleep(3600);
 +               END loop;
 +          END IF;
 +          ---
 +          IF v_LastRound > 0 THEN
 +              DBMS_SESSION.sleep(v_LastRound);
 +          END IF;          
 +    $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;
 +/
 +
 +
 +</code>
 +
 +
 +===Problem ORA-20987: APEX - Package variable g_security_group_id must be set ====
 +
 +Fehler:
 +<code sql>
 +ORA-20987: APEX - Package variable g_security_group_id must be set. - Contact your application administrator.
 +</code>
 +
 +Lösung, Security ID setzen!
 +<code sql>
 +  -- 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'));
 +  
 +</code>
 +
 +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 <fc #800000>** "PL/SQL lock timer"**</fc> der Wait Event hinter diesem Aufruf in den Wait Statistiken. 
  
 ---- ----
Zeile 48: Zeile 167:
  
 <code sql> <code sql>
-create or replace PROCEDURE sleep_java(p_milli_seconds in number) AS LANGUAGE JAVA NAME 'java.lang.Thread.sleep(long)';+create or replace PROCEDURE sleep_java(p_milli_seconds in number)  
 +  AS  
 +  LANGUAGE JAVA NAME 'java.lang.Thread.sleep(long)';
 </code> </code>
  
Zeile 54: Zeile 175:
 <fc #800000>**Nachteil:**</fc> 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. <fc #800000>**Nachteil:**</fc> 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: 
 +{{ :prog:oracle_ovjm_waits_with_java_sleep.png | OVJM Waits mit java.lang.Thread.sleep in der Datenbank }}
  
 ---- ----
Zeile 64: Zeile 186:
 Nachteil: Nachteil:
  
-  * Sicherheitsprobleme mit DBMS_LOCK habe dazugeführt das her keine Public Synonym in der DB für dieses Package vorliegt und damit ein direkter Grant benötigt wird! +  * 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! + 
 +<note warning>Ab 18c auf keine Fall mehr verwenden! Gar nicht mehr offiziell in der Doku!</note>
  
 ---- ----
Zeile 73: Zeile 195:
 ====DBMS_SESSION.sleep==== ====DBMS_SESSION.sleep====
  
-Ab der Version 18!+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!).
  
 +Aus der Doku //"The smallest increment can be entered in hundredths of a second; for example, 1.95 is a legal time value."
 +//
 +
 +Beispiel
 +<code sql>
 +
 +begin
 + dbms_session.sleep(10.45);
 +end;
 +
 +</code>
 +
 +
 +=== Problem! nur bis 3600s möglich! ===
 +
 +<code sql>
 +
 +SYS@GPI-?>BEGIN
 +  2   dbms_session.sleep(3601);
 +  3  END;
 +  4  /
 +BEGIN
 +*
 +ERROR at line 1:
 +ORA-38148: invalid time limit specified
 +ORA-06512: at "SYS.DBMS_SYS_ERROR", line 79
 +ORA-06512: at "SYS.DBMS_SESSION", line 432
 +ORA-06512: at line 2
 +</code>
 +
 +Siehe dazu den Code oben mit APEX, hier nochmal die wichigen Teile für eine Umgebung die noch 12c und 19c für die Software verwendt:
 +<code sql>
 +PROCEDURE sleep_plsql(p_seconds in number)
 +is
 +
 +  v_parts pls_integer:=0;
 +  v_LastRound pls_integer:=0;
 +  v_max_pos_seconds pls_integer:=120;
 +  v_use_java boolean:=false;
 +
 +BEGIN
 +
 +  $IF DBMS_DB_VERSION.VER_LE_12 $THEN
 +        v_max_pos_seconds:=120;
 +  $ELSE
 +        v_max_pos_seconds:=3600;
 +  $END
 +
 +   IF p_seconds/v_max_pos_seconds > 1 THEN
 +      --- floor largest integer equal to or less than
 +      v_parts:=FLOOR(p_seconds/v_max_pos_seconds);
 +      -- return the remainder
 +      v_LastRound:=MOD( p_seconds, v_max_pos_seconds );
 +   ELSE
 +      v_parts:=0;
 +      v_LastRound:=p_seconds;
 +   END IF;
 +
 +    -- if we are on 18 use the DBMS_SESSION sleep methode!
 +    $IF DBMS_DB_VERSION.VER_LE_12 $THEN
 +    
 +    ... use apex sleep see code above 
 +    
 +      
 +    $ELSE 
 +       --  DBMS_SESSION can only sleep may 3600s!     
 +       -- 
 +          IF v_parts > 0 THEN
 +              FOR i IN 1..v_parts
 +               loop
 +                 DBMS_SESSION.sleep(3600);
 +               END loop;
 +          END IF;
 +          ---
 +          IF v_LastRound > 0 THEN
 +              DBMS_SESSION.sleep(v_LastRound);
 +          END IF;          
 +   $END      
 +
 +end;
 +</code>
  
 ---- ----
prog/plsql_sleep_19c.txt · Zuletzt geändert: 2023/02/01 12:12 von gpipperr