Oracle
 sql >> Database >  >> RDS >> Oracle

Parallelizzare le chiamate in PL/SQL

Puoi usare il dbms_job (o dbms_scheduler ) per inviare lavori che verranno eseguiti in parallelo. Se stai usando dbms_job , l'invio dei lavori farà parte della transazione, quindi i lavori inizieranno una volta completata la transazione.

CREATE PACKAGE BODY pkg IS
    CREATE PROCEDURE do
    IS
      l_jobno pls_integer;
    BEGIN
        dbms_job.submit(l_jobno, 'begin other_pkg.other_proc; end;' );
        dbms_job.submit(l_jobno, 'begin other_pkg2.other_proc2; end;' );
        dbms_job.submit(l_jobno, 'begin other_pkg3.other_proc3; end;' );
    END;
END;

Se stai usando dbms_scheduler , la creazione di un nuovo lavoro non è transazionale (ovvero ci sarebbero commit impliciti ogni volta che si crea un nuovo lavoro), il che potrebbe causare problemi con l'integrità transazionale se nella transazione in cui viene chiamata questa procedura viene svolto altro lavoro. D'altra parte, se stai usando dbms_scheduler , potrebbe essere più semplice creare i lavori in anticipo ed eseguirli semplicemente dalla procedura (o utilizzare dbms_scheduler per creare una catena che esegua il lavoro in risposta a qualche altra azione o evento come mettere un messaggio in coda).

Ovviamente, con entrambe le soluzioni, dovresti quindi creare l'infrastruttura per monitorare l'avanzamento di questi tre lavori, supponendo che ti interessi quando e se hanno esito positivo (e se generano errori).

Se intendi utilizzare DBMS_SCHEDULER

  • Non è necessario utilizzare SQL dinamico. Puoi abbandonare il EXECUTE IMMEDIATE e chiama semplicemente il DBMS_SCHEDULER le procedure del pacchetto direttamente come faresti con qualsiasi altra procedura.
  • Quando chiami RUN_JOB , è necessario passare un secondo parametro. Il use_current_session parametro controlla se il lavoro viene eseguito nella sessione corrente (e si blocca) o se viene eseguito in una sessione separata (nel qual caso la sessione corrente può continuare e fare altre cose). Dato che vuoi eseguire più lavori in parallelo, dovresti passare un valore di false .
  • Sebbene non sia richiesto, sarebbe più convenzionale creare i lavori una sola volta (con auto_drop impostato su false) e quindi eseguili dalla tua procedura.

Quindi probabilmente vorresti creare i lavori al di fuori del pacchetto e quindi la tua procedura diventerebbe semplicemente

CREATE PACKAGE BODY pkg IS
    CREATE PROCEDURE do
    IS
    BEGIN
        DBMS_SCHEDULER.RUN_JOB('job_other_pkg.other_proc', false);
        DBMS_SCHEDULER.RUN_JOB('job_other_pkg2.other_proc2', false);
        DBMS_SCHEDULER.RUN_JOB('job_other_pkg3.other_proc3', false);
    END;
END;