如何解决ORA-04031错误
診斷并解決ORA-04031錯誤
??? 當我們在共享池中試圖分配大片的連續(xù)內存失敗的時候,Oracle首先清除池中當前沒使用的所有對象,使空閑內存塊合并。如果仍然沒有足夠大單個的大塊內存滿足請求,就會產生ORA-04031錯誤。
當這個錯誤出現(xiàn)的時候你得到的錯誤解釋信息類似如下:
1 [oracle@yft ~]$ oerr ora 04031 2 04031, 00000, "unable to allocate %s bytes of shared memory (\"%s\",\"%s\",\"%s\",\"%s\")" 3 // *Cause: More shared memory is needed than was allocated in the shared 4 // pool. 5 // *Action: If the shared pool is out of memory, either use the 6 // DBMS_SHARED_POOL package to pin large packages, 7 // reduce your use of shared memory, or increase the amount of 8 // available shared memory by increasing the value of the 9 // initialization parameters SHARED_POOL_RESERVED_SIZE and 10 // SHARED_POOL_SIZE. 11 // If the large pool is out of memory, increase the initialization 12 // parameter LARGE_POOL_SIZE.1、共享池相關的實例參數(shù)
??? 在繼續(xù)之前,有必要理解下面的實例參數(shù):
??????? SHARED_POOL_SIZE
??????? 這個參數(shù)指定了共享池的大小,單位是字節(jié)。可以接受數(shù)字值或者數(shù)字后面跟上后綴"K"或"M"。"K"代表千字節(jié),"M"代表兆字節(jié)。
??????? SHARED_POOL_RESERVED_SIZE
??????? 指定了為共享池內存保留的用于大的連續(xù)請求的共享池空間。當共享池碎片強制使Oracle查找并釋放大塊未使用的池來滿足當前的請求的時候,這個參數(shù)和SHARED_POOL_RESERVED_MIN_ALLOC參數(shù)一起可以用來避免性能下降。
??????? 這個參數(shù)理想的值應該大到足以滿足任何對保留列表中內存的請求掃描而無需從共享池中刷新對象。既然操作系統(tǒng)內存可以限制共享池大小,一般來說,你應該設定這個參數(shù)為SHARED_POOL_SIZE參數(shù)的10%大小。
??????? SHARED_POOL_RESERVED_MIN_ALLOC這個參數(shù)的值控制保留內存的分配。如果一個足夠尺寸的大塊內存在共享池空閑列表中沒能找到,內存就從保留列表中分配一塊比這個值大的空間。默認的值對于大多數(shù)系統(tǒng)來說都足夠了。如果你加大這個值,那么Oracle服務器將允許從這個保留列表中更少的分配并且將從共享池列表中請求更多的內存。這個參數(shù)在Oracle 8i和更高的版本中是隱藏的。提交如下的語句查找這個參數(shù)值:
SQL> col name for a20; SQL> col value for a20; SQL> select nam.ksppinm name,val.ksppstvl value2 from x$ksppi nam,x$ksppsv val3 where nam.indx = val.indx and nam.ksppinm like '%shared%'4 order by 1;??????? 10g注釋:Oracle 10g的一個新特性叫做:"自動內存管理"允許DBA保留一個共享內存池來分shared pool,buffer cache,java pool和large pool。一般來說,當數(shù)據(jù)庫需要分配一個大的對象到共享池中并且不能找到連續(xù)的可用空間,將自動使用其他SGA結構的空閑空間來增加共享池的大小。既然空間分配是Oracle自動管理的,ora-04031出錯的可能性將大大降低。自動內存管理的初始化參數(shù)SGA_TARGET大于0的時候被激活。當前設定可以通過查詢v$sga_dynamic_components視圖獲得。請參考10g管理手冊以得到更多的內容。
?2.診斷ORA-04031錯誤
??? 注:大多數(shù)的常見的ORA-04031的產生和SHARED POOL SIZE有關,這篇文章中的診斷步驟大多都是關于共享池的。對于其它方面如large_pool或是java_pool,內存分配算法都是相似的,一般來說都是因為結構不夠大造成。
??? ORA-04031可能是因為SHARED POOL不夠大,或是因為碎片問題導致數(shù)據(jù)庫不能找到足夠大的內存塊。
??? ORA-04031錯誤通常是因為庫高速緩沖中或共享池保留空間中的碎片。在加大共享池大小的時候考慮調整應用,使用共享的SQL并且調整如下的參數(shù):
??????? SHARED_POOL_SIZE,
??????? SHARED_POOL_RESERVED_SIZE,
??????? SHARED_POOL_RESERVED_MIN_ALLOC.
??? 首先判定是否ORA-04031錯誤是由共享池保留空間中的庫高速緩沖的碎片產生的。提交下面的查詢:
1 SQL> set linesize 200; 2 SQL> select free_space,avg_free_size,used_space,avg_used_size,request_failures, 3 2 last_failure_size 4 3 from v$shared_pool_reserved; 5 6 FREE_SPACE AVG_FREE_SIZE USED_SPACE AVG_USED_SIZE REQUEST_FAILURES LAST_FAILURE_SIZE 7 ---------- ------------- ---------- ------------- ---------------- ----------------- 8 4700660 167880.714 16333900 583353.571 0??? 如果:
??????????? REQUEST_FIIURES > 0 并且LAST_FAILURE_SIZE > SHARED_POOL_RESERVED_MIN_ALLOC
??? 那么ORA-04031錯誤就是因為共享池保留空間缺少連續(xù)空間所致。要解決這個問題,可以考慮加大SHARED_POOL_RESERVED_MIN_ALLOC來降低緩沖進共享池保留空間的對象數(shù)目,并增加SHARED_POOL_RESERVED_SIZE和SHARED_POOL_SIZE來加大共享池保留空間的可用內存。
??? 如果:
??????? REQUEST_FAILURES > 0 并且 LAST_FAILURE_SIZE < SHARED_POOL_RESERVED_MIN_ALLOC
??? 或者
??????? REQUEST_FAILURES?等于0 并且?LAST_FAILURE_SIZE < SHARED_POOL_RESERVED_MIN_ALLOC
??? 那么是因為在庫高速緩沖缺少連續(xù)空間導致ORA-04031錯誤。
??? 第一步應該考慮降低SHARED_POOL_RESERVED_MIN_ALLOC以放入更多的對象到共享池,保留空間中并且加大SHARED_POOL_SIZE。
3.解決ORA-04031錯誤
??? ORACLE BUG
??? Oracle推薦對你的系統(tǒng)打上最新的PatchSet。大多數(shù)的ORA-04031錯誤都和BUG相關,可以通過使用這些補丁來避免。
??? 下面表中總結和這個錯誤相關的最常見的BUG、可能的環(huán)境和修補這個問題的補丁。
???? 編譯Java代碼時出現(xiàn)的ORA-04031
???? 在你編譯Java代碼的時候如果內存溢出,你會看到錯誤:
1 A SQL exception occurred while compiling: 2 ORA-04031: unable to allocate bytes of shared memory 3 ("shared pool","unknown object","joxlod: init h","JOX: ioc_allocate_pal")??? 解決辦法是關閉數(shù)據(jù)庫然后把參數(shù)JAVA_POOL_SIZE設定為一個較大的值。這里錯誤信息中提到的"shared pool"其實共享全局區(qū)(SGA)溢出的誤導,并不表示你需要增加SHARED_POOL_SIZE,相反,你必須加大JAVA_POOL_SIZE參數(shù)的值,然后重啟系統(tǒng),再試一下。參考:<Bug:2736601>。
??? 小的共享池尺寸
??? 很多情況下,共享池過小能夠導致ORA-04031錯誤。下面信息有助于你調整共享池大小:
??????? 庫高速緩沖命中率
??????? 命中率有助于你衡量共享池的使用,有多少語句需要被解析而不是重用。下面的SQL語句有助于你計算庫高速緩沖的命中率:
1 SQL> select sum(pins) "executions", 2 2 sum(reloads) "cache misses while executing" 3 3 from v$librarycache; 4 5 executions cache misses while executing 6 ---------- ---------------------------- 7 29634 131??????? 如果丟失超過1%,那么嘗試通過加大共享池的大小來減少庫高速緩沖丟失。
??????? 共享池大小計算
??????? 要計算最合適你工作負載的共享池大小,請參考:
??????? <Note:1012046.6>:HOW TO CALCULATE YOUR SHARED POOL SIZE.
??????? 共享池碎片
??????? 每一次,需要被執(zhí)行的SQL或者PL/SQL語句的解析形式載入共享池中都需要一塊特定的連續(xù)的空間。數(shù)據(jù)庫要掃描的第一個資源就是共享池中的空閑可用內存。一旦空閑內存耗盡,數(shù)據(jù)庫要查找一塊已經分配但還沒使用的內存準備重用。如果這樣的確切尺寸的大塊內存不可用,就繼續(xù)按照如下標準尋找:
??????? 大塊(chunk)大小比請求的大小大;
??????? 空間是連續(xù)的;
??????? 大塊內存是可用的(而不是正在使用的)。
??? 這樣大塊的內存被分開,剩余的添加到相應的空閑空間列表中。當數(shù)據(jù)庫以這種方式操作一段時間之后,共享池結構就會出現(xiàn)碎片。
????當共享池存在碎片的問題,分配一片空閑的空間就會花費更多的時間,數(shù)據(jù)庫性能也會下降(整個操作的過程中,"chunk allocation"被一個叫做"shared pool latch"的閂所控制)或者是出現(xiàn)ORA-04031錯誤errors(在數(shù)據(jù)庫不能找到一個連續(xù)的空閑內存塊的時候)。
??????? 參考<Note:616223.1>:可以得到關于共享池碎片的詳細討論。
??? 如果SHARED_POOL_SIZE足夠大,大多數(shù)的ORA-04031錯誤都是由共享池中的動態(tài)SQL碎片導致的。可能的原因如下:
??????? 非共享的SQL;
????????生產不必要的解析調用(軟解析);
??????? 沒有使用綁定變量
??? 要減少碎片的產生你需要確定是前面描敘的幾種可能的因素。可以采取如下的一些方法,當然不只局限于這幾種:應用調整、數(shù)據(jù)庫調整或者實例參數(shù)調整。
??? 請參考<Note:62143.1>,描述了所有的這些細節(jié)內容。這個注釋還包括了共享池如何工作的細節(jié)。
??? 下面的視圖有助于你標明共享池中非共享的SQL/PLSQL:
???????? V$SQLAREA視圖
??????? 這個視圖保存了在數(shù)據(jù)庫中執(zhí)行的SQL語句和PL/SQL塊的信息。下面的SQL語句可以顯示給你帶有l(wèi)iteral的語句或者是帶有綁定變量的語句:
1 SQL> col sql_text for a45; 2 SQL> select substr (sql_text,1,40) "SQL",count(*), 3 2 sum (executions) "TotExecs" 4 3 from v$sqlarea 5 4 where executions < 5 6 5 group by substr (sql_text,1,40) 7 6 having count(*) > 30 8 7 order by 2;??????? 注:Having后的數(shù)值"30"可以根據(jù)需要調整以得到更為詳細的信息。
??????? X$KSMLRU視圖
??????? 這個固定表x$ksmlru跟蹤共享池中導致其它對象換出(age out)的應用。這個固定表可以用來標記是什么導致了大的應用。
??????? 如果很多對象在共享池中都被階段性的刷新可能導致響應時間問題并且有可能在對象重載入共享池中的時候導致庫高速緩沖閂競爭問題。
??????? 關于這個x$ksmlru表的一個不尋常的地方就是如果有人從表中選取內容這個表的內容就會被擦除。這樣這個固定表只存儲曾經發(fā)生的最大的分配。這個值在選擇后被重新設定這樣接下來的大的分配可以被標記,即使它們不如先前的分配過的大。因為這樣的重置,在查詢提交后的結果不可以再次得到,從表中的輸出的結果應該小心的保存。監(jiān)視這個固定表運行如下操作:
1 SQL> select * from x$ksmlru where ksmlrsiz > 0;??????? 這個表只可以用SYS用戶登錄進行查詢。
??????? X$KSMSP視圖(類似堆Heapdump信息)
??????? 使用這個視圖能找出當前分配的空閑空間,有助于理解共享池碎片的程度。如我們在前面的描述,查找為游標分配的足夠的大塊內存的第一個地方是空閑列表(free list)。下面的語句顯示了空閑列表中的大塊內存:
SQL> SELECT '0 (<140)' bucket, ksmchcls, 10 * TRUNC (ksmchsiz / 10) "From",COUNT (*) "Count", MAX (ksmchsiz) "Biggest",TRUNC (AVG (ksmchsiz)) "AvgSize", TRUNC (SUM (ksmchsiz)) "Total"FROM x$ksmspWHERE ksmchsiz < 140 AND ksmchcls = 'free' GROUP BY ksmchcls, 10 * TRUNC (ksmchsiz / 10) UNION ALL SELECT '1 (140-267)' bucket, ksmchcls, 20 * TRUNC (ksmchsiz / 20),COUNT (*), MAX (ksmchsiz), TRUNC (AVG (ksmchsiz)) "AvgSize",TRUNC (SUM (ksmchsiz)) "Total"FROM x$ksmspWHERE ksmchsiz BETWEEN 140 AND 267 AND ksmchcls = 'free' GROUP BY ksmchcls, 20 * TRUNC (ksmchsiz / 20) UNION ALL SELECT '2 (268-523)' bucket, ksmchcls, 50 * TRUNC (ksmchsiz / 50),COUNT (*), MAX (ksmchsiz), TRUNC (AVG (ksmchsiz)) "AvgSize",TRUNC (SUM (ksmchsiz)) "Total"FROM x$ksmspWHERE ksmchsiz BETWEEN 268 AND 523 AND ksmchcls = 'free' GROUP BY ksmchcls, 50 * TRUNC (ksmchsiz / 50) UNION ALL SELECT '3-5 (524-4107)' bucket, ksmchcls, 500 * TRUNC (ksmchsiz / 500),COUNT (*), MAX (ksmchsiz), TRUNC (AVG (ksmchsiz)) "AvgSize",TRUNC (SUM (ksmchsiz)) "Total"FROM x$ksmspWHERE ksmchsiz BETWEEN 524 AND 4107 AND ksmchcls = 'free' GROUP BY ksmchcls, 500 * TRUNC (ksmchsiz / 500) UNION ALL SELECT '6+ (4108+)' bucket, ksmchcls, 1000 * TRUNC (ksmchsiz / 1000),COUNT (*), MAX (ksmchsiz), TRUNC (AVG (ksmchsiz)) "AvgSize",TRUNC (SUM (ksmchsiz)) "Total"FROM x$ksmspWHERE ksmchsiz >= 4108 AND ksmchcls = 'free'GROUP BY ksmchcls, 1000 * TRUNC (ksmchsiz / 1000);BUCKET KSMCHCLS From Count Biggest AvgSize Total -------------- -------- ---------- ---------- ---------- ---------- ---------- 0 (<140) free 20 36 28 24 884 0 (<140) free 70 10 76 73 736 0 (<140) free 40 13 48 46 604 0 (<140) free 100 2 108 106 212 0 (<140) free 80 20 88 85 1708 0 (<140) free 50 15 56 52 792 0 (<140) free 30 22 36 34 764 0 (<140) free 120 7 120 120 840 0 (<140) free 60 11 68 63 696 1 (140-267) free 240 1 248 248 248 1 (140-267) free 220 1 228 228 228BUCKET KSMCHCLS From Count Biggest AvgSize Total -------------- -------- ---------- ---------- ---------- ---------- ---------- 1 (140-267) free 200 2 208 206 412 1 (140-267) free 140 1 156 156 156 2 (268-523) free 400 1 416 416 416 2 (268-523) free 450 2 476 476 952 3-5 (524-4107) free 1000 2 1424 1224 2448 3-5 (524-4107) free 500 2 880 712 1424 3-5 (524-4107) free 1500 1 1532 1532 1532 6+ (4108+) free 1646000 1 1646592 1646592 1646592 6+ (4108+) free 9000 1 9432 9432 9432 6+ (4108+) free 1915000 1 1915828 1915828 1915828 6+ (4108+) free 3891000 1 3891140 3891140 389114022 rows selected.4.ORA-04031錯誤與Large Pool
??? 大池是個可選的內存區(qū),為以下的操作提供大內存分配:
??????? MTS會話內存和Oracle XA接口;
??????? Oracle備份與恢復操作和I/O服務器進行用的內存(緩沖);
??????? 并行執(zhí)行消息緩沖。
??? 大池沒有LRU列表。這和共享池中的保留空間不同,保留空間和共享池中其他分配的內存使用同樣的LRU列表。大塊內存從不會換出大池中,內存必須是顯式的被每個會話分配并釋放。一個請求如果沒有足夠的內存,就會產生類似這樣的一個ORA-04031錯誤:
1 ORA-04031:unable to allocate XXXX bytes of shared memory 2 ("large pool","unknown object","session heap","frame")這個錯誤發(fā)生時候可以檢查幾件事情:
??????? 1).使用如下語句檢查v$sgastat,得知使用和空閑的內存:
??????? 2).你還可以采用heapdump level 32來dump大池的堆并檢查空閑的大塊內存的大小
??????? 從大池分配的內存如果是LARGE_POOL_MIN_ALLOC子節(jié)的整塊數(shù)有助于避免碎片。任何請求分配小于LARGE_POOL_MIN_ALLOC大塊尺寸都將分配LARGE_POOL_MIN_ALLOC的大小。一般來說,你會看到使用大池的時候相對共享池來說要用到更多的內存。通常要解決大池中的ORA-04031錯誤必須增加LARGE_POOL_SIZE的大小。
5.ORA-04031和共享池刷新
???? 有一些技巧提高游標的共享能力,從而共享池碎片和ORA-04031都會減少。最佳途徑是調整應用使用綁定變量。另外在應用不能調整的時候考慮使用CURSOR_SHARING參數(shù)和FORCE不同的值來做到(要注意那會導致執(zhí)行計劃改變,所以建議先對應用進行測試)。當上述技巧都不可以用的時候,并且碎片問題在系統(tǒng)中比較嚴重,刷新共享池可能有助于減輕碎片問題。但是,必須加以如下考慮:
???????? 刷新將導致所有沒有被使用的游標從共享池刪除。這樣,在共享池刷新之后,大多數(shù)SQL和PL/SQL游標必須被硬解析。這將提供CPU的使用,也會加大Latch的活動。
???????? 當應用程序沒有使用綁定變量并被需要用戶進行類似的操作的時候(如在OLTP系統(tǒng)中),刷新之后會很快還會出現(xiàn)碎片問題。所以共享池對設計糟糕的應用程序來說不是解決辦法。
???????? 對一個大的共享池刷新可能會導致系統(tǒng)掛起,尤其是實例繁忙的時候,推薦的非高峰的時候刷新
6.ORA-04031錯誤的高級分析
??? 如果前述的這些技術內容都不能解決ORA-04031錯誤,可能需要額外的跟蹤信息來得到問題發(fā)生的共享池的快照。
??? 調整init.ora參數(shù)添加如下的事件得到該問題的跟蹤信息:
event = "4031 trace name errorstack level 3"
event = "4031 trace name HEAPDUMP level 3"
??? 如果問題可重現(xiàn),該事件可設定在會話層,在執(zhí)行問題語句之前使用如下的語句:
SQL>alter session set events '4031 trace name errorstack level 3';
SQL>alter session set events '4031 trace name HEAPDUMP level 3';
??? 把這個跟蹤文件發(fā)給Oracle支持人員進行排錯。
?
轉載于:https://www.cnblogs.com/Richardzhu/articles/2922249.html
總結
以上是生活随笔為你收集整理的如何解决ORA-04031错误的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF在预览视图下可以看到图片,运行时却
- 下一篇: 55种网页常用小技巧(转载)