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