簡單講,同一個session下pageckage中的全局變量時公共的,會導(dǎo)致沖突。
以下是一些相關(guān)的資料和文章。
1
前言 在程序?qū)崿F(xiàn)過程中,經(jīng)常用遇到一些全局變量或常數(shù)。在程序開發(fā)過程中,往往會將該變量或常數(shù)存儲于臨時表或前臺程序的全局變量中,由此帶來運行效率降低<頻繁讀取臨時表>或安全隱患<存于前臺程序變量,可跟蹤內(nèi)存變量獲得>。
本文主要論述將全局變量或常數(shù)存取程序包的優(yōu)點和實現(xiàn)方法。 2 優(yōu)點 2.1
執(zhí)行效率比存儲于臨時表高,不需要頻率存取臨時表 2.2 將全局變量藏于最后防線<數(shù)據(jù)庫>,安全性較高 2.3
在視圖中可以調(diào)用程序包的變量,實現(xiàn)動態(tài)視圖 3 實現(xiàn) 3.1 實現(xiàn)方法概述
Oracle數(shù)據(jù)庫程序包中的變量,在本程序包中可以直接引用,但是在程序包之外,則不可以直接引用。對程序包變量的存取,可以為每個變量配套相應(yīng)的存儲過程<用于存儲數(shù)據(jù)>和函數(shù)<用于讀取數(shù)據(jù)>來實現(xiàn)。
Oracle存儲過程中的面向?qū)ο筇匦?/a>
1.
package的封裝 Package提供了一種封裝的機制,可以將存儲過程、方法、定值、Type放在一起。這實際上應(yīng)該是一種面向?qū)ο蟮乃枷搿ck文件包括兩部分:package
和package body。package中聲明了可用的過程、方法,package
body隱藏了實現(xiàn)的細節(jié)。 通過如上,我們即可以將位于數(shù)據(jù)庫中的表記錄數(shù)據(jù)看成是一個對象,而通過操作存儲過程,實現(xiàn)對其的訪問、修改。
2.
package內(nèi)部,type的使用 type實際上就像class或容器一樣。你可以在package內(nèi)部自主定義type,并非常方便地使用它們。如: type
my_cares is record( a number, b number, c number, d
varchar2(10) ); 定義好后,如要使用可以先聲明再直接調(diào)用。 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之間傳遞參數(shù)時,通過傳遞type
類型的參數(shù),對程序的結(jié)構(gòu)、今后的調(diào)整維護,都非常方便。
3.
package內(nèi)的參數(shù)傳遞 我們可以在package內(nèi)定義各式各樣的類型,而且它們可以作為公共參數(shù),當(dāng)在存儲過程之間傳遞時帶來便捷,就像2中所述那樣。更為主要的是,package允許定義“屬性”變量,格式如: <VariableName>
<Datatype>; 這類似Java語法,并且通過在package或package
body中聲明,可以分別作為public和private的屬性變量來使用!這些變量可以在package body begin后被初始化,并被package
body中不同的存儲過程、方法調(diào)用。
4.
其他資料 不同session執(zhí)行package又是什么情況呢?這里只引用一下相關(guān)的資料。由于package的全局變量在數(shù)據(jù)庫層次上并不可見,所以每個session都可以認為是一個被實例化了的package對象。在session級別上對全局變量執(zhí)行的賦值操作并不會被其他session看到,很好地體現(xiàn)了數(shù)據(jù)的封裝性。 而由于oracle的package并沒有顯式地創(chuàng)建實例,所以package的全局變量跟其他面向?qū)ο笳Z言的類的屬性還是有區(qū)別的。最顯著的區(qū)別在于這里的全局變量不能作為屬性值在其他procedure或者function中進行調(diào)用。如果希望達到這樣的效果,可以通過在package中定義function來實現(xiàn)。這些function的寫法,有些像Java中的getter
和 setter。
什么是session
俗來講,session
是通信雙方從開始通信到通信結(jié)束期間的一個上下文(context)。 這個上下文是一段位于服務(wù)器端的內(nèi)存:記錄了本次連接的客戶端機器,
通過那個應(yīng)用程序,那個用戶在登錄等信息。 session
是和connection同時建立的,兩者是對同一件事情不同層次的描述。簡單講,connection是物理上的客戶機同服務(wù)器段的通信鏈路,session是邏輯上的用戶同服務(wù)器的通信交互。 oracle中一個用戶登錄oracle服務(wù)器的前提,就是該用戶具有oracle的
“create
session”權(quán)限。oracle允許同一個用戶在同一個客戶機上建立多個同服務(wù)器的連接,這一點從oracle的視圖V$session中可以看到。每個session都代表了用戶與服務(wù)器的一個交互。就像兩個國家之間可以同時開展很多談判,經(jīng)濟的,環(huán)境的等等。關(guān)閉了有關(guān)經(jīng)濟的談判,不會影響到環(huán)境談判的進行。后臺進程PMON會每隔一段時間,就會測試用戶連接狀況,如果連接已斷開,PMON會清理現(xiàn)場,釋放相關(guān)的資源。 在具體的應(yīng)用場景中connction
和 session 有很多情況: 1. sqlplus 登錄
oracle 這種場景比較容易理解,一個連接對應(yīng)一個session。 2. 其他客戶端工具登錄oracle 比如:pl/sql
developer 登錄oracle。pl/sql developer 可以設(shè)置是否每個窗口共用同一個session.
如果想在調(diào)試窗口調(diào)試存儲過程或函數(shù),則必須設(shè)置為共享session。 如果設(shè)置為非共享, 則每次打開一個操作窗口,pl/sql developer
會利用最初輸入的帳戶和口令建立新的connection 和 session. 3. IIS
用程序登錄oracle 這種情況下,其實是IIS在登錄oracle。connection 和 session
的建立情況和iis機制相關(guān)。(以下是參考了網(wǎng)友的觀點,文章來源:http://www.cnblogs.com/) “對于Oracle來說,安全的Sessions數(shù)應(yīng)該為Sessions
= (IIS process number) * (min pool
size)。” IIS進程:在IIS6.0中,采用了新的進程隔離模式來響應(yīng)用戶的請求,在IIS管理器中,可以設(shè)置應(yīng)用程序池的最大進程數(shù)。對于新的WEB應(yīng)用請求,IIS進程管理器會啟動多個W3wp.exe進行響應(yīng)。 4、
其他情況 有待各路英雄補充 orcale的session內(nèi)存 oracle
的連接分為兩種:獨占式,共享式。 在獨占式連接情況下,session(如游標(biāo),排序去,sql區(qū))是在PGA中分配的。 在共享式連接情況下,session的一部分(如UGA)是在中SGA的larg
pool中分配的。 oracle session 和process oracle中每個process 都有對應(yīng)的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
相關(guān)的初始化參數(shù): process:oracle的連接數(shù)(sessions)與其參數(shù)文件中的進程數(shù)(process)相關(guān),它們的關(guān)系如下:sessions=(1.1*process+5),我們可以通過修改inia.ora的這個process參數(shù)在更改可連接的最大session數(shù)。 workarea_size_policy:PGA用手動管理還是自動管,
在AUTO的時候每個session最多能用到5%或100M.
如何跨不同session支持可讀寫的全局變量
oracle9i以上通過GLOBALLY ACCESSED
CONTEXT方式可以實現(xiàn)。但在11GR2之前,這個特性不能在RAC環(huán)境下使用,讓我們稍微感到一些遺憾.
首先,用戶必須有CREATE ANY CONTEXT權(quán)限.
為了隔離訪問,我以包的方式說明如何聲明\修改\獲取全局變量.
---- 創(chuàng)建CONTEXT并和一個包綁定: Create or Replace Context AppContext using BasePkg
ACCESSED GLOBALLY
---- 創(chuàng)建一個包來寫入變量: create or replace package BasePkg as procedure
SetAppContext( name in varchar2,value in varchar2 );
procedure init; end BasePkg; ----包體內(nèi)容
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
|