Question

I am handling millions of rows and it takes hours, so I want some feedback to give me an idea about the status of the process. It won't be possible to have real time feedback from a stored procedure since the output will be available only after the complete execution. Any solution?

Was it helpful?

Solution

There are a couple of solutions.

One is to write to a log of some description. You can use a file (writing out with UTL_FILE) or a table (using autonomous transactions so that the records are visible in another session without affecting the main transaction).

The other solution is to write to the V$SESSION_LONGOPS view using DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS. Find out more

I think logging is always a good idea with long-running background procedures. If something goes wrong your logs are the only source of info you have.

OTHER TIPS

You could have a ReportStatus procedure that writes to a different table (one you can select from while your procedure is running).

It would need a PRAGMA AUTONOMOUS_TRANSACTION so it can commit independently of your main procedure.

Example:

CREATE OR REPLACE PROCEDURE ReportStatus(status NUMBER)
AS
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  INSERT INTO StatusTable VALUES(SYSDATE, status);
  COMMIT;
END ReportStatus;
/

One more way to get feedback from running PL/SQL block is to use inter-session communication. In order to use this solution you need at least two sessions.

In audit (first) session:

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

It's going to be stuck there until first message arrives.
As the next step execute your PL/SQL block in the another (second) session:

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

Now, you can go back to the first session and see the real-time feedback from running PL/SQL block:

11:13:39: START: myBlockName

11:13:42: Updated 1000000 rows

11:13:44: Inserted 1000000 rows

Below the code of almost one line functions:

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

Tested with releases 11.2.0.4.0, 12.2.0.1.0.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top