zoukankan      html  css  js  c++  java
  • Oracle Package的全局变量与Session

    Oracle Package的全局变量与Session
    2012-07-26 aaie_ 阅 3595 转 10
    简单讲,同一个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


    -------------------------------------------------------------------------------------------------------
    Oracle数据库程序包全局变量的应用
    2012-07-26 aaie_ 阅 200 转 2
    1 前言
      在程序实现过程中,经常用遇到一些全局变量或常数。在程序开发过程中,往往会将该变量或常数存储于临时表或前台程序的全局变量中,由此带来运行效率降低<频繁读取临时表>或安全隐患<存于前台程序变量,可跟踪内存变量获得>。
      本文主要论述将全局变量或常数存取程序包的优点和实现方法。
      
    2 优点
      2.1 执行效率比存储于临时表高,不需要频率存取临时表
      2.2 将全局变量藏于最后防线<数据库>,安全性较高
      2.3 在视图中可以调用程序包的变量,实现动态视图
      
    3 实现
      3.1 实现方法概述
      Oracle数据库程序包中的变量,在本程序包中可以直接引用,但是在程序包之外,则不可以直接引用。对程序包变量的存取,可以为每个变量配套相应的存储过程<用于存储数据>和函数<用于读取数据>来实现。
      
      3.2 实例
      --定义程序包
      create or replace package PKG_System_Constant is
      
        C_SystemTitle nVarChar2(100):='测试全局程序变量'; --定义常数
        --获取常数<系统标题>
        Function FN_GetSystemTitle
         Return nVarChar2;
      
        G_CurrentDate Date:=SysDate; --定义全局变量
        --获取全局变量<当前日期>
        Function FN_GetCurrentDate
         Return Date;
        --设置全局变量<当前日期>
        Procedure SP_SetCurrentDate
         (P_CurrentDate In Date);
      End PKG_System_Constant;
      /
      create or replace package body PKG_System_Constant is
        --获取常数<系统标题>
        Function FN_GetSystemTitle
         Return nVarChar2
         Is
         Begin
           Return C_SystemTitle;
         End FN_GetSystemTitle;
      
        --获取全局变量<当前日期>
        Function FN_GetCurrentDate
         Return Date
         Is
         Begin
           Return G_CurrentDate;
         End FN_GetCurrentDate;
        --设置全局变量<当前日期>
        Procedure SP_SetCurrentDate
         (P_CurrentDate In Date)
         Is
         Begin
           G_CurrentDate:=P_CurrentDate;
         End SP_SetCurrentDate;
      End PKG_System_Constant;
      /
        
      3.3 测试
      --测试读取常数
      Select PKG_System_Constant.FN_GetSystemTitle From Dual;   
      --测试设置全局变量
      Declare 
      Begin
        PKG_System_Constant.SP_SetCurrentDate(To_Date('2001.01.01','yyyy.mm.dd'));
      End;
      /
      --测试读取全局变量
      Select PKG_System_Constant.FN_GetCurrentDate From Dual;

  • 相关阅读:
    mysql 7.5.8 服务无法启动 服务没有报告任何错误
    Ubuntu 16.04 php卸载
    函数式编程(3)-匿名函数
    函数式编程(2)-返回函数
    函数式编程(1)-高阶变成(3)-sorted
    函数式编程(1)-高阶变成(2)-filter
    函数式编程(1)-高阶变成(1)-map/reduce
    高级特性(4)-生成器
    高级特性(3)-列表生成式
    高级特性(2)-迭代
  • 原文地址:https://www.cnblogs.com/buffercache/p/10216152.html
Copyright © 2011-2022 走看看