監控批量操作進度

redhouser發表於2011-10-12

在使用PL/SQL實現批量資料處理時,通常使用DBMS_OUTPUT.put_line('step a')實現;但由於該函式並不能實時輸出(在整個PL/SQL程式碼執行結束後才輸出),無法實現進度監控的效果。
這裡摘錄楊廷琨在《OracleDBA手記3》上的方法:
1,使用自治事務將進度插入日誌表,通過查詢日誌表獲取進度
create or replace procedure p_log(p_str in varchar2) as
pragma autonomous_transaction;
begin
  insert into log values(sysdate,p_str);
  commit;
end;
/

2,使用dbms_application_info.set_action('step a')實現,通過查詢v$session.action獲取進度
begin
  dbms_application_info.set_action('step a');
end;
/

3,使用dbms_application_info.set_session_longops()實現,通過查詢v$session_longops獲取進度
set serveroutput on;
DECLARE
  --異常
  array_dml_errors EXCEPTION;
  PRAGMA EXCEPTION_INIT(array_dml_errors, -24381);

  --v$session_longops
  l_rindex BINARY_INTEGER;
  l_slno   BINARY_INTEGER;

  --error
  l_errors NUMBER;
  l_index  NUMBER;

BEGIN
  dbms_output.enable(NULL);
  dbms_output.put_line('---Begin update users_chnl.sec_id');

  l_rindex := dbms_application_info.set_session_longops_nohint;
  dbms_application_info.set_session_longops(rindex  => l_rindex,
                                            slno    => l_slno,
                                            op_name => 'update table_a',
                                            sofar   => l_batch *
                                                       con_row_limit);

EXCEPTION
  WHEN OTHERS THEN
    dbms_output.put_line(dbms_utility.format_error_stack);
    CLOSE cur;
END;
/

4,使用dbms_pipe.send_message傳送進度資訊,通過dbms_pipe.receive_message讀取進度
--監控程式
declare
  v_return number;
  v_str varchar2(32767);
begin
  v_return := dbms_pipe.create_pipe('p_test');
  while(v_return = 0) loop
    v_return := dbms_pipe.receive_message('p_test',1);
    if v_return = 0 then
      dbms_pipe.unpack_message(v_str);
      p_log(v_str);  --自治事務
    end if;
  end loop;
  v_return := dbms_pipe.remove_pipe('p_test');
end;
/     

--批量操作
declare
  v_str varchar2(4000) := 'STEP BEGIN';
  v_return number;
begin
  dbms_pipe.pack_message(v_str);
  v_return := dbms_pipe.send_message('p_test');
  dbms_lock.sleep(60);
  v_return := dbms_pipe.send_message('p_test');
  dbms_lock.sleep(60);
  v_return := dbms_pipe.send_message('p_test');
end;
/   

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/18922393/viewspace-709035/,如需轉載,請註明出處,否則將追究法律責任。

相關文章