1. 前言
在oracle數據庫實際應用過程中,經常把業務處理邏輯的放在存儲過程,客戶端通過ado進行調用。有些業務邏輯處理量大并且復雜,使客戶端調用存儲過程后,長時間沒有反應,也不知存儲過程運行狀態,本文講述如何在oracle通過任務和管道的應用,異步調用存儲過程的方法。
2. 基本原理
1.使用dbms_job包將主處理存儲過程作為任務提交到任務隊列中;
2.主處理存儲過程在運行過程中通過dbms_pipe包將處理情況放在管道中;
3.監控存儲過程讀取管道,從而了解處理情況;
4.本文沒有描述雙向通信的方式,監控存儲過程可以通過管道發送信息給主處理存儲過程。
3. 具體實現測試
建立測試環境
3.1. 對數據庫的ini進行相關修改,使系統的任務隊列功能打開
對于oracle9i,只需修設定數據庫的ini內的"job_queue_processes=非0值",如 "job_queue_processes=10",對于oracle8i除設定實例ini文件中的"job_queue_processes=非0值"外,還需設定"job_queue_interval=1"。
3.2. 設用用戶權限
由于使用oracle中特定的程序包,所以要注意要明文給于用戶系統權限。對當前用戶(測試用戶),賦于以下權力: execute dbms_pipe
execute dbms_lock
execute dbms_job
3.3. 建立模擬大業務處理存儲過程
本存儲過程通過循環30次,調用dbms_lock.sleep(1)(體眠1秒)和寫管道模擬大的處理過程。
具體代碼如下: create or replace procedure maxpro as
n integer;
status number;
begin
for n in 1..30 loop
dbms_pipe.purge('maxpro'); --清除原管道信息
dbms_pipe.pack_message(n); --把信息放入緩沖區
status:=dbms_pipe.send_message('maxpro');
dbms_lock.sleep(1);
end loop;
dbms_pipe.purge('maxpro'); --清除原管道信息
dbms_pipe.pack_message(999999); --把信息放入緩沖區,用999999 表示過程完成
status:=dbms_pipe.send_message('maxpro');
end maxpro;
3.4. 建立讀取管道動態了解處理狀態的存儲過程
以下代碼是對于maxpro存儲過程的狀態進行讀取的過程,主要使用讀取管道的方法,注意: status:= dbms_pipe.receive_message('maxpro',0);
中的"0"參數是很關鍵的,說明接受等待時間為0秒,表示,調用時如果沒有信息不等待直接返回。
具體代碼如下: create or replace procedure readmaxpro as
n integer;
status integer;
begin
--接受等待時間為1秒,可以為0,立即調用或
dbms_pipe.receive_message('mypipe') 等待100天
status:= dbms_pipe.receive_message('maxpro',0);
--status為0為成功可以unpack_message,1為超時沒有數據,
2為信息太大,3為內部錯誤
if status <> 0 then
dbms_output.put_line('管道中現在沒有信息返回');
return;
end if;
dbms_pipe.unpack_message(n);
dbms_output.put_line('maxpro 的當前進行狀態為'|| n);
end;
3.5. -起動模擬大業務處理存儲過程為后臺進程的存儲過程(beginmaxpro)
通過dbms_job.submit(job,'maxpro;',sysdate,null,false);使"maxpro"為一個任務,在當前時間(sysdate)后執行,當然如果把sysdate改一具體時間,那就在具體時間執行。
具休代碼如下: create or replace procedure beginmaxpro as
job binary_integer;
begin
dbms_job.submit(job,'maxpro;',sysdate,null,false);
dbms_output.put_line('隊列號碼job=' || job);
commit;
end;
4. 代碼執行
4.1. 執行過程
在cmd行輸入 sqlplus 根據提示登錄
設定dbms_output可見
sql> set serveroutput on
以下是執行過程和相應的返回信息
sql> call beginmaxpro();
隊列號碼job=21
調用完成。
sql> call readmaxpro();
maxpro 的當前進行狀態為14
調用完成。
sql> call readmaxpro();
maxpro 的當前進行狀態為16
調用完成。
sql> call readmaxpro();
maxpro 的當前進行狀態為23
調用完成。
sql> call readmaxpro();
maxpro 的當前進行狀態為999999
調用完成。
sql> call readmaxpro();
管道中現在沒有信息返回
調用完成。
sql>4.2. 執行分析
beginmaxpro(),將主處理存儲過程放入隊列的過程,執行后存儲程序馬上返回,maxpro存儲過程放在任務隊列中,并設定為在當前系統時間執行(馬上執行)。
maxpro為主處理存儲過程,開始執行模擬大業務處理,處理過程中將處理進度信息寫入管道。
readmaxpro();為檢查狀態存儲過程,首先讀取信息,如果信息不存在,說明管道內沒有信息可讀而退出;如果存在信息則讀出信息。
本例子可以進行改進,輸出不通過dbms_output.put_line而是用返回值,那么就可以在前端用ado調用,發布任務,任務過程中從客戶端讀取進度。代碼如下: create or replace procedure readmaxpro(p out intergr) as
n integer;
status integer;
begin
status:= dbms_pipe.receive_message('maxpro',0);
if status <> 0 then
p:=-1;
return;
end if;
dbms_pipe.unpack_message(p);
end;
新聞熱點
疑難解答