programing

Oracle에서 PL/SQL 출력을 플러시하는 방법이 있습니까?

javajsp 2023. 3. 10. 21:05

Oracle에서 PL/SQL 출력을 플러시하는 방법이 있습니까?

셸 스크립트 내에서 호출되는 SQL 스크립트가 있어 실행하는 데 시간이 오래 걸립니다.현재 다음을 포함합니다.dbms_output.put_line여러 가지 점에서 진술합니다.이러한 인쇄문의 출력은 로그 파일에 표시됩니다.단, 스크립트가 완료된 후에만 표시됩니다.

스크립트가 실행 중일 때 로그 파일에 출력이 표시되도록 하는 방법이 있습니까?

사실 그렇지 않아요.DBMS_OUTPUT의 동작 방법은 다음과 같습니다.PL/SQL 블록은 클라이언트와의 상호 작용 없이 데이터베이스 서버에서 실행됩니다.그래서 PUT에 전화하면...LINE, 이 텍스트는 서버상의 메모리에 있는 버퍼에 격납되어 있습니다.PL/SQL 블록이 완료되면 제어가 클라이언트에 반환됩니다(이 경우 SQLPlus를 가정합니다).이 시점에서 클라이언트는 GET_LINE을 호출하여 버퍼에서 텍스트를 가져와 표시합니다.

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

다른 방법으로는 UTL_FILE을 사용하여 텍스트파일에 쓰거나 자율 트랜잭션 절차를 사용하여 데이터베이스 테이블에 디버깅문을 삽입하고 각 파일 뒤에 커밋하는 방법도 있습니다.

가능한 경우 dbms_output 호출을 대체해야 합니다.put_line은 사용자 고유의 기능으로 사용할 수 있습니다.

다음은 이 함수의 코드입니다. 2개의 로깅 솔루션 중 하나를 선택할 수 있는 기능을 가진 경우:

자율 트랜잭션의 테이블에 로그 쓰기

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 서버에 직접 쓰거나

Oracle 디렉토리를 사용합니다.

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

그런 다음 두 가지 용도를 전환하거나 성능 손실을 방지하기 위해 비활성화할 수 있는 절차(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

두 가지 대안:

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

  2. 또 다른 방법은 로깅 정보를 반환하는 파이프라인 함수를 사용하는 것입니다.예를 들어 http://berxblog.blogspot.com/2009/01/pipelined-function-vs-dbmsoutput.html 파이프라인 함수를 사용할 경우 다른 SQLPLUS/Toad/sql 개발자 등을 사용할 필요가 없습니다.세션입니다.

of충의 DBMS_OUTPUT.DBMS_OUTPUT.get_line합니다.클라이언트 애플리케이션이 SQL*Plus인 경우 절차가 완료된 후에만 해당 애플리케이션이 플러시됨을 의미합니다.

SO에서 설명된 방법을 적용하여 다음을 작성할 수 있습니다.DBMS_OUTPUT파일로 버퍼링합니다.

를 사용하여 및을 설정합니다.dbms_application_info().
OEM을 OEM) §:

Module: ArchiveData
Action: xxx of xxxx

PL/SQL 환경에서 시스템셸에 액세스 할 수 있는 경우는, netcat 를 호출할 수 있습니다.

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

p_msg입니다. - 로그 메시지입니다.v_host를 실행하고 이 스크립트는 python 포트 상의 .이 스크립트는 포트 상의 소켓에서 데이터를 읽습니다.v_port.

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

언급URL : https://stackoverflow.com/questions/1472587/is-there-any-way-to-flush-output-from-pl-sql-in-oracle