Oracle Package的全域變數與Session

來源:互聯網
上載者:User

簡單講,同一個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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.