Oracle Package的全局变量与Session

简单讲,同一个session下pageckage中的全局变量时公共的,会导致冲突。

以下是一些相关的资料和文章。

 

Oracle数据库程序包全局变量的应用

1 前言
  在程序实现过程中,经常用遇到一些全局变量或常数。在程序开发过程中,往往会将该变量或常数存储于临时表或前台程序的全局变量中,由此带来运行效率降低<频繁读取临时表>或安全隐患<存于前台程序变量,可跟踪内存变量获得>。
  本文主要论述将全局变量或常数存取程序包的优点和实现方法。
2 优点
  2.1 执行效率比存储于临时表高,不需要频率存取临时表
  2.2 将全局变量藏于最后防线<数据库>,安全性较高
  2.3 在视图中可以调用程序包的变量,实现动态视图
3 实现
  3.1 实现方法概述
  Oracle数据库程序包中的变量,在本程序包中可以直接引用,但是在程序包之外,则不可以直接引用。对程序包变量的存取,可以为每个变量配套相应的存储过程<用于存储数据>和函数<用于读取数据>来实现。

Oracle存储过程中的面向对象特性

1. package的封装
Package提供了一种封装的机制,可以将存储过程、方法、定值、Type放在一起。这实际上应该是一种面向对象的思想。pck文件包括两部分:package 和package body。package中声明了可用的过程、方法,package body隐藏了实现的细节。
通过如上,我们即可以将位于数据库中的表记录数据看成是一个对象,而通过操作存储过程,实现对其的访问、修改。

2. package内部,type的使用
type实际上就像class或容器一样。你可以在package内部自主定义type,并非常方便地使用它们。如:
type my_cares is record(
a number,
b number,
c number,
d varchar2(10)
);
定义好后,如要使用可以先声明再直接调用。
declare
the_care my_cares;
i number := 0;
begin
the_care.a := 1;
the_care.b := 2;
i := the_care.b;
dbms_output.put_line(‘value is ’ || the_care.d);
end;
在procedure之间传递参数时,通过传递type 类型的参数,对程序的结构、今后的调整维护,都非常方便。

3. package内的参数传递
我们可以在package内定义各式各样的类型,而且它们可以作为公共参数,当在存储过程之间传递时带来便捷,就像2中所述那样。更为主要的是,package允许定义“属性”变量,格式如:
<VariableName> <Datatype>;
这类似Java语法,并且通过在package或package body中声明,可以分别作为public和private的属性变量来使用!这些变量可以在package body begin后被初始化,并被package body中不同的存储过程、方法调用。

4. 其他资料
不同session执行package又是什么情况呢?这里只引用一下相关的资料。由于package的全局变量在数据库层次上并不可见,所以每个session都可以认为是一个被实例化了的package对象。在session级别上对全局变量执行的赋值操作并不会被其他session看到,很好地体现了数据的封装性。
而由于oracle的package并没有显式地创建实例,所以package的全局变量跟其他面向对象语言的类的属性还是有区别的。最显著的区别在于这里的全局变量不能作为属性值在其他procedure或者function中进行调用。如果希望达到这样的效果,可以通过在package中定义function来实现。这些function的写法,有些像Java中的getter 和 setter。

什么是session

俗来讲,session 是通信双方从开始通信到通信结束期间的一个上下文(context)。
这个上下文是一段位于服务器端的内存:记录了本次连接的客户端机器, 通过那个应用程序,那个用户在登录等信息。
session 是和connection同时建立的,两者是对同一件事情不同层次的描述。简单讲,connection是物理上的客户机同服务器段的通信链路,session是逻辑上的用户同服务器的通信交互。
oracle中一个用户登录oracle服务器的前提,就是该用户具有oracle的 “create session”权限。oracle允许同一个用户在同一个客户机上建立多个同服务器的连接,这一点从oracle的视图V$session中可以看到。每个session都代表了用户与服务器的一个交互。就像两个国家之间可以同时开展很多谈判,经济的,环境的等等。关闭了有关经济的谈判,不会影响到环境谈判的进行。后台进程PMON会每隔一段时间,就会测试用户连接状况,如果连接已断开,PMON会清理现场,释放相关的资源。
在具体的应用场景中connction 和 session 有很多情况:
1.        sqlplus 登录 oracle
这种场景比较容易理解,一个连接对应一个session。
2.        其他客户端工具登录oracle
比如:pl/sql developer 登录oracle。pl/sql developer 可以设置是否每个窗口共用同一个session. 如果想在调试窗口调试存储过程或函数,则必须设置为共享session。
如果设置为非共享, 则每次打开一个操作窗口,pl/sql developer 会利用最初输入的帐户和口令建立新的connection 和 session.
3.        IIS 用程序登录oracle
这种情况下,其实是IIS在登录oracle。connection 和 session 的建立情况和iis机制相关。(以下是参考了网友的观点,文章来源:http://www.cnblogs.com/
“对于Oracle来说,安全的Sessions数应该为Sessions = (IIS process number) * (min pool size)。”
IIS进程:在IIS6.0中,采用了新的进程隔离模式来响应用户的请求,在IIS管理器中,可以设置应用程序池的最大进程数。对于新的WEB应用请求,IIS进程管理器会启动多个W3wp.exe进行响应。
4、 其他情况 有待各路英雄补充
orcale的session内存
oracle 的连接分为两种:独占式,共享式。
在独占式连接情况下,session(如游标,排序去,sql区)是在PGA中分配的。
在共享式连接情况下,session的一部分(如UGA)是在中SGA的larg pool中分配的。
oracle session 和process
   oracle中每个process 都有对应的session。
   process 分为
       用户进程在V$session 中可用条件:$session.type = 'USER'.查询。
       后台进程在V$session 中可用条件:$session.type =  'BACKGROUND'查询。
       常见的后台进程:
SMON,PMON,DBWR,LGWR,MMAN,MRP, RFS,RECO,CKPT,ARCH,Dnnn,Snnn,LMON,LMD0,QMNn,TRWR,WMON,LCKnnn,SNPnnn, MMON,DMON,SNP
session 相关的初始化参数:
process:oracle的连接数(sessions)与其参数文件中的进程数(process)相关,它们的关系如下:sessions=(1.1*process+5),我们可以通过修改inia.ora的这个process参数在更改可连接的最大session数。
workarea_size_policy:PGA用手动管理还是自动管, 在AUTO的时候每个session最多能用到5%或100M.

 

如何跨不同session支持可读写的全局变量

    oracle9i以上通过GLOBALLY ACCESSED CONTEXT方式可以实现。但在11GR2之前,这个特性不能在RAC环境下使用,让我们稍微感到一些遗憾.

      首先,用户必须有CREATE ANY CONTEXT权限.

      为了隔离访问,我以包的方式说明如何声明\修改\获取全局变量.

---- 创建CONTEXT并和一个包绑定:
Create or Replace Context AppContext using BasePkg ACCESSED GLOBALLY

---- 创建一个包来写入变量:
create or replace package BasePkg
as
   procedure SetAppContext( name       in varchar2,value      in varchar2 );

   procedure init;
end BasePkg;
----包体内容

create or replace package body BasePkg

as

   G_SESSION_ID  Constant Number := -1;

procedure init
    IS
    begin

       NULL;
     end;

    procedure SetAppContext( name       in varchar2,value      in varchar2 )

    as
    begin
            dbms_session.setAppContext ( 'FMIS_BASE', name, value, NULL, G_SESSION_ID );
    end;
begin
     dbms_session.set_identifier( g_session_id ); 
end BasePkg ;
--- 每次初始化以后

EXEC BasePkg .init;

--就可以跨session,访问全局变量了

select sys_context( 'FMIS_BASE' ,'变量名' )  from dual

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wga168/archive/2010/06/30/5704401.aspx

posted @ 2010-12-08 11:54  laughter  阅读(4650)  评论(0编辑  收藏  举报