6
votes

Avoir des sorties pl / sql en temps réel

est-il possible d'avoir des sorties de PL / SQL en temps réel? J'ai un paquet assez énorme qui fonctionne pendant plus d'une heure et j'aimerais voir où se trouve le colis à un moment donné.

Quoi qu'il en soit, je le fais actuellement avec une table en rondins, qui est remplie de centaines de descriptions de journaux par exécution, je suis juste curieux si cela est possible.

Merci!


0 commentaires

6 Réponses :


8
votes

Je ne sais pas si c'est exactement ce que vous voulez, mais j'utilise dbms_application_info.set_module pour voir où mon colis est. xxx

requête sur v $ session vous montrera quelle partie de la procédure est en cours d'exécution.


0 commentaires

4
votes

Vous pouvez utiliser Transactions autonomes (comme suggéré dans Cela est donc par exemple) .

Cela vous permettrait d'écrire et de vous engager dans une table de journaux sans que la transaction principale. Vous seriez alors en mesure de suivre ce qui se passe dans votre script principal lorsqu'il est en cours d'exécution (incidemment, cela vous permettra également de choisir votre lot).


1 commentaires

+1 Il existe également une bonne description dans «Oracle Pl / SQLProgramming» de Feuerstein, qui est également disponible dans Google Books.



9
votes

C'est le genre de chose que j'utilise (on peut voir la sortie dans V $ Session et V $ session_longops) ...

DECLARE
   lv_module_name   VARCHAR2(48);
   lv_action_name   VARCHAR2(32);

   gc_MODULE   CONSTANT   VARCHAR2(48) := 'MY_PROC';

   -- For LONGOPS
   lv_rindex BINARY_INTEGER;
   lv_slno   BINARY_INTEGER;

   lc_OP_NAME   CONSTANT   VARCHAR2(64)   :=   '['||gc_MODULE||']';
   lv_sofar   NUMBER;

   -- This is a guess as to the amount of work we will do
   lv_totalwork   NUMBER;
   lc_TARGET_DESC   CONSTANT VARCHAR2(64) := 'Tables';
   lc_UNITS   CONSTANT VARCHAR2(64) := 'Rows';

   CURSOR tab_cur
   IS
      SELECT owner, table_name
        FROM all_tables;

BEGIN
   <<initialisation>>
   BEGIN
      -- To preserve the calling stack, read the current module and action
      DBMS_APPLICATION_INFO.READ_MODULE( module_name => lv_module_name
                                       , action_name => lv_action_name );

      -- Set our current module and action
      DBMS_APPLICATION_INFO.SET_MODULE( module_name => gc_MODULE
                                      , action_name => NULL );
   END initialisation;

   <<main>>
   BEGIN
      DBMS_APPLICATION_INFO.SET_ACTION( action_name => 'Part 01' );
      NULL;

      DBMS_APPLICATION_INFO.SET_ACTION( action_name => 'Part 02' );
      FOR tab_rec IN tab_cur
      LOOP
         DBMS_APPLICATION_INFO.SET_CLIENT_INFO( client_info => 'Rows = ['||TO_CHAR( tab_cur%ROWCOUNT, '999,999,999' )||']' );
         NULL;
      END LOOP;

      DBMS_APPLICATION_INFO.SET_ACTION( action_name => 'Part 03' );

      --Initialising longops
      lv_rindex := DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS_NOHINT;
      lv_sofar := 0;
      lv_totalwork := 5000; -- This is a guess, but could be actual if the query is quick

      FOR tab_rec IN tab_cur
      LOOP
         DBMS_APPLICATION_INFO.SET_CLIENT_INFO( client_info => 'Rows = ['||TO_CHAR( tab_cur%ROWCOUNT, '999,999,999' )||']' );

         lv_sofar := lv_sofar + 1;

         -- Update our totalwork guess
         IF lv_sofar > lv_totalwork
         THEN
            lv_totalwork := lv_totalwork + 500;
         END IF;

         DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS( rindex      => lv_rindex
                                                  , slno        => lv_slno
                                                  , op_name     => lc_OP_NAME
                                                  , sofar       => lv_sofar
                                                  , totalwork   => lv_totalwork
                                                  , target_desc => lc_TARGET_DESC
                                                  , units       => lc_UNITS
                                                  );
      END LOOP;

      -- Clean up longops
      DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS( rindex      => lv_rindex
                                               , slno        => lv_slno
                                               , op_name     => lc_OP_NAME
                                               , sofar       => lv_sofar
                                               , totalwork   => lv_sofar
                                               , target_desc => lc_TARGET_DESC
                                               , units       => lc_UNITS
                                               );
   END main;

   <<finalisation>>
   BEGIN
      -- Reset the module and action to the values that may have called us
      DBMS_APPLICATION_INFO.SET_MODULE( module_name => lv_module_name
                                      , action_name => lv_action_name );

      -- Clear the client info, preventing any inter process confusion for anyone looking at it
      DBMS_APPLICATION_INFO.SET_CLIENT_INFO( client_info => NULL );
   END finalisation;
END;
/


0 commentaires

1
votes

Utilisez dbms_pipe pour écrire un message à un tuyau nommé. Dans une autre session, vous pouvez lire les messages du tuyau. Très simple, fonctionne comme un charme!

procedure sendmessage(p_pipename varchar2
                        ,p_message  varchar2) is
      s number(15);
   begin
      begin
         sys.dbms_pipe.pack_message(p_message);
      exception
         when others then
            sys.dbms_pipe.reset_buffer;
      end;

      s := sys.dbms_pipe.send_message(p_pipename, 0);

      if s = 1
      then
         sys.dbms_pipe.purge(p_pipename);
      end if;
   end;




function receivemessage(p_pipename varchar2
                          ,p_timeout  integer) return varchar2 is
      n   number(15);
      chr varchar2(200);
   begin
      n := sys.dbms_pipe.receive_message(p_pipename, p_timeout);

      if n = 1
      then
         return null;
      end if;

      sys.dbms_pipe.unpack_message(chr);
      return(chr);
   end;


0 commentaires

1
votes

Si votre travail de longue date traite un grand nombre de tâches de taille assez équitablement, vous trouverez peut-être une session Longops un bon moyen de surveiller les progrès de l'emploi, ainsi que de vous permettre d'estimer combien de temps le travail prendra à la fin.

dbms_application_info.set_session_longops


0 commentaires

0
votes

Si vous avez accès à Shell à partir de l'environnement PL / SQL, vous pouvez appeler Netcat:

commencez run_shell ('echo "' '|| v_msg ||'" | nc '|| v_host ||' '|| v_port ||' -w 5 '); Fin;

/

v_host est un script Python d'hôte qui lit les données de la prise sur le port v_port .

J'ai utilisé cette conception lorsque j'ai écrit aplogrez pour Shell et Surveillance des journaux PL / SQL.


0 commentaires