2009-09-24 12 views
33

Ho uno script SQL chiamato da uno script di shell e richiede molto tempo per essere eseguito. Attualmente contiene le dichiarazioni dbms_output.put_line in vari punti. L'output di queste istruzioni di stampa viene visualizzato nei file di registro, ma solo una volta completato lo script.Esiste un modo per svuotare l'output da PL/SQL in Oracle?

C'è un modo per garantire che l'output venga visualizzato nel file di registro mentre lo script è in esecuzione?

risposta

46

Non proprio. Il modo in cui funziona DBMS_OUTPUT è questo: il blocco PL/SQL viene eseguito sul server del database senza interazione con il client. Quindi quando chiami PUT_LINE, sta semplicemente mettendo quel testo in un buffer in memoria sul server. Al termine del blocco PL/SQL, il controllo viene restituito al client (in questo caso suppongo SQLPlus); a quel punto il client ottiene il testo dal buffer chiamando GET_LINE e lo visualizza.

Quindi l'unico modo in cui è possibile visualizzare l'output nel file di registro con maggiore frequenza è quello di suddividere un grande blocco PL/SQL in più blocchi più piccoli, in modo che il controllo venga restituito al client più spesso. Questo potrebbe non essere pratico a seconda di cosa sta facendo il tuo codice.

Altre alternative sono l'uso di UTL_FILE per scrivere in un file di testo, che può essere scaricato in qualsiasi momento, oppure utilizzare una procedura di transazione autonoma per inserire istruzioni di debug in una tabella di database e eseguire il commit dopo ciascuna di esse.

4

il buffer di DBMS_OUTPUT viene letto quando viene richiamata la procedura DBMS_OUTPUT.get_line. Se l'applicazione client è SQL * Plus, significa che verrà svuotata solo al termine della procedura.

È possibile applicare il metodo descritto in this SO per scrivere il buffer DBMS_OUTPUT in un file.

6

due alternative:

  1. È possibile inserire i tuoi dati di registrazione in una tabella di registrazione utilizzando una transazione autonoma. È possibile interrogare questa tabella di registrazione in un'altra sessione SQLPLUS/Toad/sql per lo sviluppatore ecc. È necessario utilizzare una transazione autonoma per rendere possibile il commit della registrazione senza interferire con la gestione della transazione nello script sql principale.

  2. Un'altra alternativa consiste nell'utilizzare una funzione pipeline che restituisce le informazioni di registrazione. Vedi qui per un esempio: http://berxblog.blogspot.com/2009/01/pipelined-function-vs-dbmsoutput.html Quando si utilizza una funzione pipeline, non è necessario utilizzare un'altra sessione SQLPLUS/Toad/sql per lo sviluppatore ecc.

3

Se è possibile, è necessario sostituire le chiamate a dbms_output.put_line con la propria funzione.

Ecco il codice per questa funzione WRITE_LOG - se si vuole avere la possibilità di scegliere tra 2 soluzioni di registrazione:

i registri di scrittura per un tavolo in un autonomous transaction

CREATE OR REPLACE PROCEDURE to_dbg_table(p_log varchar2) 
    -- table mode: 
    -- requires 
    -- CREATE TABLE dbg (u varchar2(200) --- username 
    --     , d timestamp  --- date 
    --     , l varchar2(4000) --- log 
    --); 
AS 
    pragma autonomous_transaction; 
BEGIN 
    insert into dbg(u, d, l) values (user, sysdate, p_log); 
    commit; 
END to_dbg_table; 
/

o scrivere direttamente sul server DB che ospita il database

Questo utilizza il Oracle directoryTMP_DIR

CREATE OR REPLACE PROCEDURE to_dbg_file(p_fname varchar2, p_log varchar2) 
    -- file mode: 
    -- requires 
--- CREATE OR REPLACE DIRECTORY TMP_DIR as '/directory/where/oracle/can/write/on/DB_server/'; 
AS 
    l_file utl_file.file_type; 
BEGIN 
    l_file := utl_file.fopen('TMP_DIR', p_fname, 'A'); 
    utl_file.put_line(l_file, p_log); 
    utl_file.fflush(l_file); 
    utl_file.fclose(l_file); 
END to_dbg_file; 
/


WRITE_LOG

Poi la procedura WRITE_LOG che può commutare tra le 2 usi, o essere attivato t o evitare la perdita di prestazioni (g_DEBUG:=FALSE).

CREATE OR REPLACE PROCEDURE write_log(p_log varchar2) AS 
    -- g_DEBUG can be set as a package variable defaulted to FALSE 
    -- then change it when debugging is required 
    g_DEBUG boolean := true; 
    -- the log file name can be set with several methods... 
    g_logfname varchar2(32767) := 'my_output.log'; 
    -- choose between 2 logging solutions: 
    -- file mode: 
    g_TYPE varchar2(7):= 'file'; 
    -- table mode: 
    --g_TYPE varchar2(7):= 'table'; 
    ----------------------------------------------------------------- 
BEGIN 
    if g_DEBUG then 
    if g_TYPE='file' then 
     to_dbg_file(g_logfname, p_log); 
    elsif g_TYPE='table' then 
     to_dbg_table(p_log); 
    end if; 
    end if; 
END write_log; 
/

Ed ecco come per testare quanto sopra:

1) Lanciare questo (modalità file) dal SQLPLUS:

BEGIN 
    write_log('this is a test'); 
    for i in 1..100 loop 
    DBMS_LOCK.sleep(1); 
    write_log('iter=' || i); 
    end loop; 
    write_log('test complete'); 
END; 
/

2) sul server di database, aprire un shell e

 
    tail -f -n500 /directory/where/oracle/can/write/on/DB_server/my_output.log 
+0

Speriamo che nessuno usi tabelle con nomi di colonne come 'u, d, l' ... – Obenland

+0

@Oberland, i nomi di tabelle e colonne non sono importanti se il framework che gestisci i tuoi utenti è corretto. Hai mai lavorato per una banca con database di vecchia scuola? Vale la pena. –

+0

Suppongo che tu intendessi "peggio";) – quetzalcoatl

0

Se si ha accesso alla shell di sistema da PL/SQL envi biente è possibile chiamare netcat:

BEGIN RUN_SHELL('echo "'||p_msg||'" | nc '||p_host||' '||p_port||' -w 5'); END; 

p_msg - è un messaggio di log v_host è uno script python host che esegue che legge i dati dal socket sulla porta v_port.

Ho usato questo disegno quando ho scritto aplogr per il monitoraggio dei registri shell e pl/sql in tempo reale.

+0

Si prega di non aggiungere [la stessa risposta] (collegamento) a più domande. Rispondi al migliore e contrassegna il resto come duplicato. Vedi [È accettabile aggiungere una risposta duplicata a diverse domande?] (Http://meta.stackexchange.com/q/104227/347985) – Mogsdad

Problemi correlati