1

我正在处理数百万行,这需要几个小时,所以我需要一些反馈来让我了解流程的状态。不可能从存储过程中获得实时反馈,因为只有在完成执行后才能获得输出。有什么解决办法吗?

4

3 回答 3

4

有几个解决方案。

一种是写入一些描述的日志。您可以使用文件(使用 UTL_FILE 写出)或表(使用自治事务,以便记录在另一个会话中可见,而不会影响主事务)。

另一种解决方案是使用 DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS 写入 V$SESSION_LONGOPS 视图。找到更多

我认为记录长期运行的后台程序总是一个好主意。如果出现问题,您的日志是您拥有的唯一信息来源。

于 2012-10-30T09:18:25.823 回答
2

您可以有一个写入不同表的 ReportStatus 过程(您可以在过程运行时从中选择一个)。

它需要一个 PRAGMA AUTONOMOUS_TRANSACTION 以便它可以独立于您的主程序提交。

例子:

CREATE OR REPLACE PROCEDURE ReportStatus(status NUMBER)
AS
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  INSERT INTO StatusTable VALUES(SYSDATE, status);
  COMMIT;
END ReportStatus;
/
于 2012-10-30T09:20:28.287 回答
2

从运行的 PL/SQL 块中获取反馈的另一种方法是使用会话间通信。为了使用此解决方案,您至少需要两个会话。

在审计(第一次)会议中:

set head off arrays 1 pages 0 feedback off timing off
select column_value notification from table (notificationReceive);

在第一条消息到达之前,它将被卡在那里。
作为下一步,在另一个(第二个)会话中执行您的 PL/SQL 块:

begin 
    notificationSend ('START: '||'myBlockName');
    /* UPDATE table1 SET col1 = value ... WHERE some condition;
    */ dbms_lock.sleep(3);
    notificationSend ('Updated 1000000 rows'); -- sql%rowcount instead of literal 
    /* INSERT INTO table2 (val1, SYSDATE, v_user_id);
    */ dbms_lock.sleep(2);
    notificationSend ('Inserted 1000000 rows'); 
    notificationSend ('ENDTX');
end;
/

现在,您可以回到第一个会话并查看运行 PL/SQL 块的实时反馈:

11:13:39: START: myBlockName

11:13:42: Updated 1000000 rows

11:13:44: Inserted 1000000 rows

下面是几乎一行函数的代码:

create or replace procedure notificationSend (message varchar2) is
pragma autonomous_transaction;
begin
    dbms_alert.signal ('feedback$_queue', message);
    commit;
end;
/
create or replace function notificationReceive return sys.odciVarchar2List pipelined is
pragma autonomous_transaction;
    message varchar2(1800) := 'NONE';
    status number := -1;
begin 
    dbms_alert.register('feedback$_queue');
    <<reading>> loop 
        dbms_alert.waitone('feedback$_queue', message, status); 
        if status = 0 and message != 'ENDTX' then
            pipe row (to_char (sysdate, 'hh:mi:ss')||': '||message);
            pipe row (null); -- dummy row for prefetch in sqlplus 
        else 
            exit reading; 
        end if;
    end loop reading;
    dbms_alert.remove('feedback$_queue');
    return;
end;
/

使用版本 11.2.0.4.0、12.2.0.1.0 进行测试。

于 2018-05-20T15:31:45.707 回答