2009-09-24 3 views
33

쉘 스크립트 내에서 호출되는 SQL 스크립트가 있으며 실행하는 데 오랜 시간이 걸립니다. 현재 다양한 지점에서 dbms_output.put_line 문장이 포함되어 있습니다. 이러한 인쇄 명령문의 출력은 로그 파일에 표시되지만 스크립트가 완료된 후에 만 ​​표시됩니다.Oracle의 PL/SQL에서 출력을 플러시 할 수 있습니까?

스크립트가 실행 중일 때 출력이 로그 파일에 나타나는지 확인하는 방법이 있습니까?

답변

46

아니요. DBMS_OUTPUT이 작동하는 방식은 다음과 같습니다. PL/SQL 블록은 클라이언트와 상호 작용하지 않고 데이터베이스 서버에서 실행됩니다. 따라서 PUT_LINE을 호출하면 서버의 메모리 버퍼에 텍스트가 저장됩니다. PL/SQL 블록이 완료되면 클라이언트 (이 경우 SQLPlus라고 가정)로 제어가 리턴됩니다. 이 시점에서 클라이언트는 GET_LINE을 호출하여 버퍼에서 텍스트를 가져 와서 표시합니다.

출력을 로그 파일에 더 자주 표시 할 수있는 유일한 방법은 대형 PL/SQL 블록을 여러 개의 작은 블록으로 분할하여 제어가 클라이언트에 더 자주 리턴되는 것입니다. 이것은 코드가하는 일에 따라 실용적이지 않을 수 있습니다.

다른 대안은 UTL_FILE을 사용하여 언제든지 삭제할 수있는 텍스트 파일에 쓰거나, 자율 트랜잭션 프로 시저를 사용하여 디버그 문을 데이터베이스 테이블에 삽입하고 각각을 수행 한 후 커밋하는 것입니다.

4

절차 DBMS_OUTPUT.get_line을 호출하면 DBMS_OUTPUT의 버퍼가 읽혀집니다. 클라이언트 응용 프로그램이 SQL * Plus 인 경우 프로 시저가 완료된 후에 만 ​​플러시됩니다.

this SO에 설명 된 방법을 적용하여 DBMS_OUTPUT 버퍼를 파일에 쓸 수 있습니다.

6

두 대안 :

  1. 당신은 자율 트랜잭션을 사용하여 로깅 테이블 로깅 정보를 삽입 할 수 있습니다. 다른 SQLPLUS/Toad/sql 개발자 등 세션에서이 로깅 테이블을 쿼리 할 수 ​​있습니다. 주요 SQL 스크립트에서 트랜잭션 처리를 방해하지 않고 로깅을 커밋 할 수있게하려면 자치 트랜잭션을 사용해야합니다.

  2. 또 다른 대안은 로깅 정보를 반환하는 파이프 라인 된 함수를 사용하는 것입니다. 예제를 보려면 다음을 참조하십시오. http://berxblog.blogspot.com/2009/01/pipelined-function-vs-dbmsoutput.html 파이프 라인 기능을 사용하면 다른 SQLPLUS/Toad/sql 개발자 등 세션을 사용할 필요가 없습니다.

3

가능한 경우 dbms_output.put_line에 대한 호출을 사용자 고유의 기능으로 바꿔야합니다.여기

이 기능 WRITE_LOG 코드입니다 - 당신이 개 로깅 솔루션을 선택할 수있는 능력을 갖고 싶어 : 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; 
/

또는 데이터베이스를 호스팅하는 DB 서버에 직접 쓰기

,는

이것은 2 개 용도를 전환하거나 비활성화 t 될 수 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

이어서 WRITE_LOG 절차를 사용하여 o 공연 손실을 피하십시오 (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; 
/

그리고 테스트하는 방법입니다 위 :

1) 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), 열려면 쉘 및

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

아무도 'u, d, l'과 같은 열 이름이있는 테이블을 사용하지 않기를 바랍니다. – Obenland

+0

@ Oberland, 사용자를 처리하는 프레임 워크가 올바른 경우 표 및 열 이름은 중요하지 않습니다. BTW 이전 학교 데이터베이스가있는 은행에서 일해 본 적이 있습니까? 그것보다 가치가 있습니다. –

+0

나는 '나쁜'을 의미한다고 생각합니다.) – quetzalcoatl

0

PL/SQL 환경에서 시스템 쉘에 액세스 할 수있는 경우 당신이 netcat을 호출 할 수 있습니다 했었다는 :

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

p_msg이 - 로그 메시지 v_host 것은 포트 v_port에 소켓에서 데이터를 읽어 호스트 실행 파이썬 스크립트입니다.

실시간 쉘 및 pl/sql 로그 모니터링을 위해 aplogr을 작성할 때이 디자인을 사용했습니다.

+0

여러 질문에 [같은 대답] (링크)을 추가하지 마십시오. 가장 좋은 답변을하고 나머지는 중복으로 표시하십시오. [여러 질문에 대한 중복 답변을 추가해도됩니까?] (http://meta.stackexchange.com/q/104227/347985)를 참조하십시오. – Mogsdad

관련 문제