`
wolongshan
  • 浏览: 68536 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

ORACLE的存储过程的异步调用

阅读更多
ORACLE的存储过程的异步调用
作者:王辉 来源:赛迪网 发布时间:2003.05.26
 

  1. 关于作者

  王辉 从1994年开始工作,曾担任教师、数据库管理员、主程序员、项目经理,现在深圳一家公司担任项目经理。可以通过ddxxkk@21cn.com联系。

  2. 前言

  在ORACLE数据库实际应用过程中,经常把业务处理逻辑的放在存储过程,客户端通过ADO进行调用。有些业务逻辑处理量大并且复杂,使客户端调用存储过程后,长时间没有反应,也不知存储过程运行状态,本文讲述如何在ORACLE通过任务和管道的应用,异步调用存储过程的方法。

  3. 基本原理

    1.使用DBMS_JOB包将主处理存储过程作为任务提交到任务队列中

    2.主处理存储过程在运行过程中通过DBMS_PIPE包将处理情况放在管道中

    3.监控存储过程读取管道,从而了解处理情况

    4.本文没有描述双向通信的方式,监控存储过程可以通过管道发送信息给主处理存储过程

  4. 具体实现测试

  建立测试环境

  4.1. 对数据库的ini进行相关修改,使系统的任务队列功能打开

  对于ORACLE9I,只需修设定数据库的INI内的"JOB_QUEUE_PROCESSES=非0值",如 "JOB_QUEUE_PROCESSES=10",对于ORACLE8I除设定实例ini文件中的"JOB_QUEUE_PROCESSES=非0值"外,还需设定"job_queue_interval=1"

  4.2. 设用用户权限

  由于使用ORACLE中特定的程序包,所以要注意要明文给于用户系统权限。对当前用户(测试用户),赋于以下权力

EXECUTE DBMS_PIPE
EXECUTE DBMS_LOCK
EXECUTE DBMS_JOB

  4.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;

  4.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;

  4.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;

  5. 代码执行

  5.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>

  5.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;

  6. 附录:

  6.1. 相关程序包说明

1   
DBMS_JOB.SUBMIT(
   JOB OUT BINARY_INTEGER,
   WHAT IN VARCHAR2,
   NEXT_DATE IN DATE DEFAULTSYSDATE, 
   INTERVAL IN VARCHAR2 DEFAULT 'NULL',
   NO_PARSE IN BOOLEAN DEFAULT FALSE,
   INSTANCE IN BINARY_INTEGER DEFAULT ANY_INSTANCE,
   FORCE IN BOOLEAN DEFAULT FALSE)
   功能:提交作业入作业队列
   参数说明:
   JOB:作业的作业号,输出参数
   WHAT:作业对应的PL/SQL代码(一般用于过程名)
   NEXT_DATE:下一次作业运行的时间
   INTERVAL:作业执行间隔时间,缺省是NULL,只执行一次
   NO_PARSE:是否对WHAT语句,在提交时进行分析,缺省是进行分析。
   INSTANCE:作业提交时,指明运行作业的实例,缺省是0,任何的数据库全可以
   FORCE:是否检查INSTANCE指定的数据库在运行,缺省是FALSE,不检查
   例子:
 declare
	 jobn number;
	 begin
		 DBMS_JOB.SUBMIT(jobn,'maxpro;',sysdate);
		 DBMS_OUTPUT.PUT_LINE('JOB=' || jobn);
		 COMMIT;
	 end;

  注意:

  设定数据库参数JOB_QUEUE_PROCESSES = 非0值(最大队列数最大60)

  对于9I前设定数据库参数JOB_QUEUE_INTERVAL = 非0值(队列扫描周期1-3600秒)

  2

DBMS_PIPE.PACK_MESSAGE       (item  IN  VARCHAR2);
DBMS_PIPE.PACK_MESSAGE       (item  IN  NCHAR);
DBMS_PIPE.PACK_MESSAGE       (item  IN  NUMBER);
DBMS_PIPE.PACK_MESSAGE       (item  IN  DATE);
DBMS_PIPE.PACK_MESSAGE_RAW   (item  IN  RAW);
DBMS_PIPE.PACK_MESSAGE_ROWID (item  IN  ROWID);
功能:把一个数据项放到私有数据缓冲区

3

DBMS_PIPE.SEND_MESSAGE (
    pipename     IN VARCHAR2,
    timeout      IN INTEGER DEFAULT MAXWAIT,
    maxpipesize  IN INTEGER DEFAULT 8192)
  RETURN INTEGER;
  功能:发送私有数据缓冲区的信息到命名管道,如果管道不存在就建立

 

4

DBMS_PIPE.RECEIVE_MESSAGE (
   pipename     IN VARCHAR2,
   timeout      IN INTEGER      DEFAULT maxwait)  RETURN INTEGER;
  功能:从管道到接受信息放到数据缓冲区

5

DBMS_PIPE.UNPACK_MESSAGE       (item  OUT VARCHAR2);
DBMS_PIPE.UNPACK_MESSAGE       (item  OUT NCHAR);
DBMS_PIPE.UNPACK_MESSAGE       (item  OUT NUMBER);
DBMS_PIPE.UNPACK_MESSAGE       (item  OUT DATE);
DBMS_PIPE.UNPACK_MESSAGE_RAW   (item  OUT RAW);
DBMS_PIPE.UNPACK_MESSAGE_ROWID (item  OUT ROWID);
功能:从数据缓冲区接收下一个数据项

6

DBMS_PIPE.PURGE ( pipename  IN  VARCHAR2);
功能:清除管道内的信息

 

 

(责任编辑:西门吹风
分享到:
评论
2 楼 wolongshan 2010-09-20  
谁有更简单的方式呢?我也觉得复杂
1 楼 sun_wind 2010-07-28  
采用这种机制太复杂了

相关推荐

    Oracle数据库中存储过程的异步调用

    本文讲述如何在Oracle通过任务和管道的应用,异步调用存储过程的方法。并且介绍了其基本原理和具体实现测试。

    Java调用oracle存储过程总结

    Java调用oracle存储过程

    Oracle数据库异步调用基本原理及测试

    在Oracle数据库实际应用过程中,经常把业务...有些业务逻辑处理量大并且复杂,使客户端调用存储过程后,长时间没有反应,也不知存储过程运行状态,本文讲述如何在Oracle通过任务和管道的应用,异步调用存储过程的方法。

    Oracle存储过程中任务和管道的应用

    在ORACLE数据库实际应用过程中有些业务逻辑处理量大并且复杂,使客户端调用存储过程后,长时间没有反应,也不知存储过程运行状态,本文讲述如何在ORACLE通过任务和管道的应用,异步调用存储过程的方法。

    异步并行加载工具Asyncload.zip

    针对方法调用,基于字节码增强技术,运行时生成代理类,快速返回mock对象,后台异步进行调用通过管理和调度线程池,将后台异步调用进行加速处理,达到一个平衡点业务执行过程需要获取mock对象的真实数据时,阻塞等待...

    Oracle9i的init.ora参数中文说明

    说明: 用于指定数据库为远程 PL/SQL 存储的过程处理被依赖对象的方式。如果设置为 TIMESTAMP, 只有在服务器与本地时间戳相匹配的情况下, 才能执行该过程。如果设置为 SIGNATURE, 在签名安全的情况下即可执行该过程。...

    DemoUtils:一些帮助类

    13、数据库操作帮助类以及简单的调用存储过程【Oracle-查询】 14、String 15、Set 16、Thread【实现方式、异步调用、join、synchronized、wait、notifyAll,死锁、同步互斥、通信、ThreadLocal、消费者与生产者模式...

    asp.net知识库

    发布Oracle存储过程包c#代码生成工具(CodeRobot) New Folder XCodeFactory3.0完全攻略--序 XCodeFactory3.0完全攻略--基本思想 XCodeFactory3.0完全攻略--简单示例 XCodeFactory3.0完全攻略--IDBAccesser ...

    Java面试宝典2020修订版V1.0.1.doc

    19、用JDBC如何调用存储过程 69 20、JDBC中的PreparedStatement相比Statement的好处 71 21、写一个用jdbc连接实例。 71 22、ArrayList和Vector的区别? 73 23、List、Set和Map的区别? 74 24、Collection 和 ...

    odbc-api:Rust的ODBC(开放数据库连接)绑定

    支持存储过程的输出参数。 支持准备好的和“一次性”查询。 交易次数 将参数传递给查询 支持异步 支持多线程 动机 支持在Rust中编写ODBC Application。 该领域的先前工作已完成: odbc-sys :裸露到ODBC C库...

    java开源包1

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    Activiti6.0.0最新源码

    Activiti6版本仅保留了Activiti5版本中的异步作业执行器(async executor)。定时作业被划分了四个不同的表:executable jobs, timer jobs, suspended jobs 和deadletter jobs。引擎可以更快的执行作业。定时器作业...

    亮剑.NET深入体验与实战精要2

    7.8 实现异步调用Web Service 297 7.9 如何保证Web Service的安全 299 7.9.1 通过SoapHeader来增强 Web Service的安全性 299 7.9.2 采用SSL实现加密传输 302 7.9.3 访问IP限制 315 7.10 Web Service开发中需要注意的...

    亮剑.NET深入体验与实战精要3

    7.8 实现异步调用Web Service 297 7.9 如何保证Web Service的安全 299 7.9.1 通过SoapHeader来增强 Web Service的安全性 299 7.9.2 采用SSL实现加密传输 302 7.9.3 访问IP限制 315 7.10 Web Service开发中需要注意的...

    Hmily柔性分布式事务解决方案-其他

    在性能上,日志存储异步(可选)以及使用异步执行的方式,不损耗业务方法方法。之前是由我个人开发,目前由我在京东数科已经重新启动,未来将会是金融场景的分布式事务解决方案。 功能: 高可靠性:支持分布式场景下...

    C#.net_经典编程例子400个

    122 实例092 为控件制作立体效果 122 实例093 获取控件名称和内容 124 第3章 组件应用 127 3.1 BackgroundWorker组件 128 实例094 BackgroundWorker组件执行异步操作 128 3.2 ...

    超级有影响力霸气的Java面试题大全文档

    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。 20、abstract class和interface有什么区别? ...

    java 面试题 总结

    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。 17、abstract class和interface有什么区别? 声明方法...

    千方百计笔试题大全

    234、存储过程和函数的区别 55 235、事务是什么? 55 236、游标的作用?如何知道游标已经到了最后? 55 237、触发器分为事前触发和事后触发,这两种触发有和区别。语句级触发和行级触发有何区别。 56 238、EJB容器...

Global site tag (gtag.js) - Google Analytics