1. 程式人生 > >ORA-04031 無法分配 12519000 位元組的共享記憶體 large pool , unknown obje

ORA-04031 無法分配 12519000 位元組的共享記憶體 large pool , unknown obje

               

author:skatetime: 2009/04/14

ORA-04031: 無法分配 12519000 位元組的共享記憶體 ("large pool","unknown object","hash-join subh","kllcqc:kllcqslt")

解決方法:

SQL> show parameter dispa

NAME                                 TYPE        VALUE------------------------------------ ----------- ------------------------------dispatchers                          string      (PROTOCOL=TCP)max_dispatchers                      integer     5mts_dispatchers                      string      (PROTOCOL=TCP)mts_max_dispatchers                  integer     5

sql> alter system set dispatchers='(PROTOCOL=TCP)(SERVICE=orclXDB)';

SQL> show parameter dispa

NAME                                 TYPE        VALUE------------------------------------ ----------- ------------------------------dispatchers                          string      (PROTOCOL=TCP)(SERVICE=orclXDB                                                 )max_dispatchers                      integer     5mts_dispatchers                      string      (PROTOCOL=TCP)(SERVICE=orclXDB                                                 )mts_max_dispatchers                  integer     5

問題解決,再用select × from v$session 檢視 ,都是dedicated連線了

後者指定了服務名,而前者沒有。沒有指定伺服器,大概就造成了oracle例項向listener註冊時,以任何服務名來建立的連線都是使用shared server方式。這是個人理解。

相關知識總結:

Oracle Shared Server比較適合一些小而快的事務連線,這些事務的特點就是事務比較短,操作和返回的資料量比較少。而對於一些資料倉庫而言,顯然是不適合建成 Shared Server模式。下面說一下Shared Server和Dedicated Server的一些區別:

在Dedicated Server環境中,每一個連線都將啟動一個專用服務程序,這個專用服務程序始終服務於這個連線直到連線斷開。每一個專用服務程序都有一個屬於自己的記憶體區域,叫做PGA(Program GlobalArea),裡面存放了會話的資訊,包括繫結變數、遊標、排序等等。

而在Shared Server環境中,這些資訊被存放到SGA中的UGA(User Global Area)區域中,這個區域一般都位於大型池中(Large pool)

 shared_server structure

在Shared Server環境中,一個排程器服務多個連線的請求,並將請求放到請求佇列(request queue)中,所有排程器共用一個請求佇列,接著由共享服務程序(Shared Server processes)來處理這些請求,並將處理後的結果返回到響應佇列(response queue),與請求佇列不同,每個排程器都有自己的一個響應佇列,然後由排程器把響應佇列中的結果返回給客戶端。其中請求佇列和響應佇列都是SGA中的一部分。在一個共享服務環境中,一個客戶端請求的步驟是這樣的:

1、 客戶端傳送一個請求到排程器2、 排程器將請求放入到請求佇列中3、 共享服務程序從請求佇列中取出請求進行處理4、 共享服務程序將處理後的結果放到排程器的響應佇列中5、 排程器從響應佇列中取出結果返回給客戶端

同時,在Shared server環境中,也可以使用連線池的方法來存放多個連線請求,資料庫定時斷開空閒的連線來服務其它新的連線請求。

在Shared server環境中也存在不足,當某一個請求需要處理並返回大量資料的時候,將會導致其它新的請求得不到及時的響應。所以對於這樣的請求,最好使用專用服務程序。同時,部分資料庫管理操作需要使用專用服務程序,比如資料庫啟動關閉,資料庫備份恢復等等,對於表分析、大量資料載入、索引重建等操作也建議使用專用服務程序。

監聽器在Shared server環境中也扮演著重要的角色。PMON程序定期檢測排程器的負載情況,並將這些資訊反饋給監聽器。監聽器記錄著每個排程器的地址資訊及負載情況(當前服務多少個連線等等),當有新的連線請求的時候,監聽器將負載較低的排程器地址資訊返回給客戶端,客戶端根據地址資訊連線到相應的排程器。

如果使用者程序不能夠連線到排程程序,或者使用者請求的是一個專有伺服器連線,則監聽器將建立一個專有伺服器程序(dedicated server process),並把這個使用者程序連線到這個伺服器程序

shared_server structure

下面談談如何配置Oracle shared server環境。

可以通過多種方法來配置shared server,包括建立資料庫的時候指定引數、EM、修改初始化引數檔案,還有可以通過Alter system進行修改,因為這些引數都是動態引數。

設定連線池:dispatchers="(protocol=tcp)(serv=orcl)(list=orcl)(pool=on)(TICK=1)(disp=5)(con=33)(sess=224)

上面表示啟動連線池,一個排程器的連線數最大為33個,sessions數目最大為224個,並10分鐘後自動斷開未活動的連線。(TICK=1表示10分鐘)

shared_servers:指定oracle啟動時,啟動的共享伺服器程序的最小數量,對於很繁忙的系統,這個值設定的大一些               對於很空閒的系統,這個值設定的小一些,對於一般的系統這個值設定是連線數的十分之一,        預設值庫1。設定為0表示不使用SHARED_SERVER。

dispatchers 用於設定排程程序,其中,protocol用於設定排程程序支援的協議,poo用於設定是否啟用共享程序;poo=on表示啟用共享程序,disp用於設定排程程序的數量;con使用者設定每個排程程序3的最大網路連線數量;sess使用者設定每個排程程序的最大會話數(session)。排程器數量 = 資料庫最大session數 /每個排程器服務的session數;

dispatchers還有如下屬性:

service:dispatcher註冊的net service name,沒有給出採用services_name中的;listener:監聽動態註冊,非預設埠1521或沒有在local_listener中給出時需使用;sessions:每個dispacther的會話數connections:每個dispacther連線數

MAX_DISPATCHERS:設定最大的排程器數,可以動態調整,如:ALTER SYSTEM SET MAX_DISPATCHERS=10;

SHARED_SERVER_SESSIONS:設定ORACLE SHARED SERVER的最大session數。當連線到SHARED SERVER的session數超過此值的話,將報錯:ERROR:ORA-00018 maximum number of sessions exceeded

不過當資料庫session超過此值的時候,仍然可以通過專用伺服器連線進行連線。

 MAX_SHARED_SERVERS:設定最大的SHARED_SERVER數。如果未給此引數附值,那麼SHARED_SERVER數庫無限制。

原來oracle服務在註冊到監聽器是預設到1521埠的,如果沒有註冊上則監聽的狀態始終會為unknow狀態,不過客戶端通過tns的配置專用服務請求還是能找到相應的資料服務的,但是共享服務就沒有辦法了,因為埠不是預設的1521,因此共享伺服器的排程器dispatcher找不到監聽所在的埠41521,因此找不到排程服務,至使與監聽不能互相通訊。

上面連線就講了如何讓oracle服務註冊到特殊的監聽埠。其實很簡單:在oracle資料庫伺服器上配置上本地的oracle的tnsname連線。sdb =(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = sdb)(PORT =41521)))(CONNECT_DATA =(SID = sdb)(SERVER = DEDICATED)))

然後修改引數:alter system set local_listener = "sdb";alter system register;之前local_listener是為空的,此時本地oracle服務就知道可以通過sdb這個tnsname到本地的監聽伺服器進行註冊,狀態變成了ready,這時排程器也一併被進行了註冊。

資料庫的session數可以通過下面的檢視獲得:1、 v$session:獲得當前資料庫的session數SQL> select count(*) from v$session where username is not null;2、 V$LICENSE:獲得當前資料庫的session數及資料庫啟動以來最大的session數SQL> select sum(sessions_current) cur_sessions,sum(sessions_highwater) high_sessions from V$LICENSE;比如資料庫當前有500個TCP/IP session,每個排程器管理50個session,那麼就需要10(500/50)個排程器。引數設定如下:DISPATCHERS=”(PRO=TCP)(DIS=10)”當然也可以根據資料庫當前的負載,使用ALTER SYSTEM命令動態的增加或減少排程器的資料,如下:ALTER SYSTEM SET DISPATCHERS=”(PRO=TCP)(DIS=5)”;

2)從動態效能圖獲得資訊:V$CIRCUIT  :select * from v$circuit;V$QUEUEV$SESSIONV$DISPATCHER:顯示當前排程器的一些資訊,包括排程器的狀態(等待還是繁忙)、當前的連線數、歷史的連線數等等。V$DISPATCHER_CONFIG:顯示排程器的一些配置引數。V$SHARED_SERVER:顯示當前資料庫SHARED SERVER的一些狀態資訊V$SHARED_SERVER_MONITOR:顯示當前資料庫SHARED SERVER的一些統計資訊,包括SHARED SERVER的最大連線數,會話數及啟動的SHARED SERVER數等等。同時,在ORACLE SHARED SERVER環境中,也可以配置專用伺服器連線,但只有當你是使用Localnaming方法的時候才可以,如果你是使用Hostnaming方法的話則不可以。有幾個方法進行配置,如下:1、 手工修改Tnsname檔案ora10g =(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.172)(PORT = 1521)))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = ora10g)))2、通過Oracle net manager進行配置

3)對於配置了ORACLE SHARED SERVER的資料庫,有一些引數需要值得我們的關注:1、LARGE POOL SIZE在ORACLE SHARED SERVER環境中,ORACLE 將UGA存放在LARGE POOL中,而在沒有LARGE POOL或者LARGE POOL太小的資料庫中,UGA將存放於SHARED POOL中,這樣將影響到資料庫其它的效能。所以LARGE POOL的大小也值得我們考究。LARGE POOL最小為300K,最大為2G(不同作業系統可能有所不同)。一般來講,在ORACLE SHARED SERVER環境中,一個連線將佔用1-3M的記憶體,不過要看會話做了哪些操作。我們可以通過下面的語句獲得資料庫啟動以來,最大的UGA值:

select sum(value) "Max MTS Memory Allocated"from v$sesstat ss, v$statname stwhere name = 'session uga memory max'and ss.statistic# =st.statistic#;Max MTS Memory Allocated------------------------------------244416

可以看到,ORACLE分配的最大UGA庫240K,如果資料庫同時支援100個併發連線,那麼可以將LARGE POOL設定庫23M(240K*100)。如果LARGE POOL設定過小,可能遇到下面的錯誤:ORA-04031: unable to allocate 490 bytes of shared memory("large pool","MWEIS","session heap","define var info")可以通過ALTER SYSTEM命令進行動態修改。ALTER SYSTEM SET LARGE_POOL_SIZE = 51200000 SCOPE=SPFILE;2、 排程器數目可以通過查詢V$DISPATCHER檢視來檢視排程器的狀態:SQL> desc v$dispatcher;Name Type Nullable Default Comments--------- ------------- -------- ------- --------NAME VARCHAR2(4) Y NETWORK VARCHAR2(128) Y PADDR RAW(4) Y STATUS VARCHAR2(16) Y ACCEPT VARCHAR2(3) Y MESSAGES NUMBER Y BYTES NUMBER Y BREAKS NUMBER Y OWNED NUMBER Y CREATED NUMBER Y IDLE NUMBER Y BUSY NUMBER Y LISTENER NUMBER Y CONF_INDX NUMBER Y SQL> Select name, (busy / (busy + idle))*1002 "Dispatcher % busy Rate"3 From V$DISPATCHER4 /NAME Dispatcher % busy Rate---- ----------------------D000 0.0052861386871346如果繁忙的百分比超過50%,那麼可以考慮增加排程器,可以使用下面的語句動態修改:ALTER SYSTEM SET DISPATCHERS=“(PRO=TCP)(DIS=2)”;3、 排程器響應時間可以通過檢視V$QUEUE 和 V$DISPATCHER來獲得連線等待排程器響應的時間:SELECT decode(sum(totalq),0,’No Responses’,Sum(wait)/sum(totalq)) “Average Wait time”FROM V$QUEUE q, V$DISPATCHER dWHERE q.type = ‘DISPATCHER’AND q.paddr = d.paddr;Average Wait Time------------------.04134、 連線等待shared server處理請求的時間Select decode(totalq,0,’No Requests’) “Wait Time”,Wait/totalq || ‘ hundredths of seconds’“Average Wait time per request”from V$QUEUEwhere type = ‘COMMON’Wait Time Average Wait time per request-------- -----------------------------------.023132 hundredths of a second 

1。是否為配置為共享伺服器,最主要的引數是

8i mts_servers

9i shared_server

show parameter shared_server mts_servers

如果數值 > 0 ,就是enable了共享伺服器.

2。在配置為共享伺服器的情況,Client可以選擇用共享伺服器或者專用伺服器來連線到資料庫,這個引數的控制是在tnsnames.ora裡設定的

aaaa=

(DESCRIPTION =

(ADDRESS_LIST =

(ADDRESS = (PROTOCOL = TCP)(HOST = aaaa)(PORT = 1521))

)

(CONNECT_DATA =

(SID = aa)

(SERVER = DEDICATED)

)

)

紅色部分指定了用DEDICATED方式連線DB.

另外,Background process ,以及通過本地連線進來的,只能是DEDICATED

比如說sqlplus user/pass 形式

如果DB沒有配置共享伺服器,那麼Client只能以DEDICATED方式連線DB.(1. 如果是dedicated server,則客戶端只能建立dedicated server connection2. 如果是shared server,則客戶端能建立dedicated server connection和shared server connection,只要在service name中指定server=dedicated or server=shared.)

3.判斷一個已經連線的session的連線方式有兩種方法

A

select username,server from v$session;

如果server = 'DEDICATED'則是DEDICATED方式

server='SHARED'則是shared方式,並且正有shared_server_process為其服務

server='NONE'的話,則是shared方式,並且當前沒有shared_server_process為其服務。

B. 僅用於Unix 底下,似乎windown不行

連線v$session, v$process 看process中的program

1 select p.program,s.server from v$session s , v$process p

2* where s.paddr = p.addr

如果 program 為 。。(S0NN) 的,則是shared方式,並且正有shared_server_process為其服務

如果 program 為 。。(D0NN) 的,則是shared方式,並且當前沒有shared_server_process為其服務

如果 program 為 其它的,則是'DEDICATED'方式

參考文件:

-----續-----