我正在处理数百万行,这需要几个小时,所以我想要一些反馈,让我了解一下这个过程的状态。由于输出仅在完成执行后才可用,因此无法从存储过程获得实时反馈。任何解决方案?
答案 0 :(得分:4)
有几种解决方案。
一种是写入某些描述的日志。您可以使用文件(writing out with UTL_FILE)或表格(使用autonomous transactions,以便在不影响主要交易的情况下在另一个会话中显示记录。)
另一种解决方案是使用DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS写入V $ SESSION_LONGOPS视图。 Find out more
我认为使用长时间运行的后台程序记录总是一个好主意。如果出现问题,您的日志是您拥有的唯一信息来源。
答案 1 :(得分: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;
/
答案 2 :(得分: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进行测试。