程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> Oracle存儲過程中任務和管道的應用

Oracle存儲過程中任務和管道的應用

編輯:Oracle數據庫基礎

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;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved