在Oracle中有没有办法刷新PL/SQL的输出?

在Oracle中有没有办法刷新PL/SQL的输出?,sql,oracle,plsql,dbms-output,Sql,Oracle,Plsql,Dbms Output,我有一个SQL脚本,它是从shell脚本中调用的,需要很长时间才能运行。它当前包含dbms\u输出。在不同的点上放置行语句。这些打印语句的输出显示在日志文件中,但仅在脚本完成后显示 有没有办法确保脚本运行时输出显示在日志文件中?调用过程DBMS\u output.get\u line时读取DBMS\u output的缓冲区。如果您的客户端应用程序是SQL*Plus,则意味着只有在过程完成后才会刷新它 您可以应用中所述的方法将DBMS\u输出缓冲区写入文件。实际上不是这样。DBMS_输出的工作方式

我有一个SQL脚本,它是从shell脚本中调用的,需要很长时间才能运行。它当前包含
dbms\u输出。在不同的点上放置行
语句。这些打印语句的输出显示在日志文件中,但仅在脚本完成后显示


有没有办法确保脚本运行时输出显示在日志文件中?

调用过程
DBMS\u output.get\u line
时读取
DBMS\u output
的缓冲区。如果您的客户端应用程序是SQL*Plus,则意味着只有在过程完成后才会刷新它


您可以应用中所述的方法将
DBMS\u输出
缓冲区写入文件。

实际上不是这样。DBMS_输出的工作方式是:PL/SQL块在数据库服务器上执行,而不与客户机交互。因此,当您调用PUT_LINE时,它只是将文本放入服务器内存中的缓冲区中。当PL/SQL块完成时,控制返回给客户机(在本例中,我假设为SQLPlus);此时,客户端通过调用GET_LINE从缓冲区中获取文本,并显示它

因此,使输出更频繁地出现在日志文件中的唯一方法是将大型PL/SQL块分解为多个较小的块,以便更频繁地将控制权返回给客户机。这可能不实用,这取决于您的代码正在做什么

其他替代方法是使用UTL_文件写入文本文件,文本文件可以随时刷新,或者使用自治事务过程将调试语句插入数据库表,并在每个语句之后提交。

两种替代方法:

  • 您可以使用自治事务在日志表中插入日志详细信息。您可以在另一个SQLPLUS/Toad/sqldeveloper等中查询此日志记录表。。。一场您必须使用自治事务,以便在不干扰主sql脚本中的事务处理的情况下提交日志记录

  • 另一种选择是使用管道函数返回日志信息。请参阅此处的示例:当您使用流水线函数时,不必使用其他SQLPLUS/Toad/sql开发人员等。。。会议


  • 如果可能,您应该用自己的函数替换对dbms_output.put_line的调用

    以下是此功能的代码
    写入日志
    ——如果您希望能够在两种日志解决方案之间进行选择:

    将日志写入 或者直接写入托管数据库的DB服务器 这使用了TMP\U目录

    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;
    /
    

    写入日志
    然后,
    写入日志
    过程可以在两种使用之间切换,或者被停用以避免性能损失(
    g\u DEBUG:=FALSE

    下面是如何测试上述各项: 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) 在数据库服务器上,打开一个shell并

    tail-f-n500/directory/where/oracle/can/write/on/DB_server/my_output.log
    如果您可以从PL/SQL环境访问system shell,则可以调用netcat:

     BEGIN RUN_SHELL('echo "'||p_msg||'" | nc '||p_host||' '||p_port||' -w 5'); END;
    
    p_msg
    -是一条日志消息
    v_-host
    是一个运行python脚本的主机,该脚本从端口
    v_-port
    上的套接字读取数据


    我在编写实时shell和pl/sql日志监控时使用了这种设计。

    使用
    dbms\u application\u info()设置会话元数据模块和/或操作

    使用OEM进行监控,例如:

    Module: ArchiveData
    Action: xxx of xxxx
    

    请不要在多个问题中添加[相同答案](链接)。回答最好的一个,并将其余的标记为重复项。请参阅,您也可以直接监视ASH(v$active\u session\u history)
     BEGIN RUN_SHELL('echo "'||p_msg||'" | nc '||p_host||' '||p_port||' -w 5'); END;
    
    Module: ArchiveData
    Action: xxx of xxxx