buffer cache 和shared pool詳解 診斷和解決ORA-04031 錯誤

kunlunzhiying發表於2016-12-19
  老熊

http://blog.csdn.net/panfelix/article/details/38347853




ORA-04031這個錯誤,幾乎每一個專業的DBA都遇到過。這是一個相當嚴重的錯誤,Oracle程式在向SGA申請記憶體時,如果申請失敗,則會報這個錯誤。大部分情況下是在向SGA中的shared pool申請記憶體時失敗,而少有向large pool等池中申請記憶體失敗。比如下面的報錯:

  1. Wed Apr 27 16:00:25 2011  
  2. Errors in file /oracle/app/oracle/admin/zxin/bdump/zxin1_ora_2052294.trc:  
  3. ORA-04031: unable to allocate 4128 bytes of shared memory   
  4. ("shared pool","unknown object","sga heap(3,0)","kgllk hash table")  

這裡很清楚地表示出來,是在向shared pool申請記憶體時失敗。

shared pool記憶體申請(分配)失敗,通常有如下的幾種可能:

  • shared pool過小,比如在SGA Manual Management方式下,shared pool設定過小。比如一套數千連線的大系統,shared pool只設定了幾百M。這種情況下,要解決問題很解單,增加shared pool的大小即可。
  • 應用沒有使用繫結變數,硬解析非常多,導致shared pool記憶體碎片嚴重,分配大塊記憶體時不能獲得連續的記憶體空間。硬解析多的一個變種是雖然使用了繫結變數,但是由於某種原因,Cursor不能共享,導致Child Cursor非常多。實際上,如果shared pool較大(比如數GB大小),這種問題還是很少出現的,並且出現也通常出現在申請大塊記憶體時。這種情況如果使用alter system flush shared_pool可以暫時緩解問題。但是這條命令又通常不適用於shared pool較大而且比較繁忙的系統。使用繫結變數
  • Cache的cursor很多,同時cursor_space_for_time這一引數設定為TRUE,可能會使shared pool碎片化嚴重,導致不能分配到大塊的連續記憶體。
  • Oracle的BUG導致記憶體洩露,比如在一些版本中查詢v$segment_statistics這樣的檢視導致記憶體洩露,使shared pool記憶體耗光。同樣的情形還有類似於“obj stat memory”,"gcs resources","ges resources"等。通常這類記憶體為perm型別(permanet),這類記憶體通常是在分配時就確定了固定的用途,不能用於其他用途,因此極容易產生碎片。
  • Oracle從9i開始,根據shared pool的大小將shared pool分為多個子池(subpool),每個子池有獨立的free list,同時在分配時單獨管理(有其獨立 的shared pool latch)。Oracle的BUG或者說是記憶體分配策略缺陷導致某一類shared pool的記憶體分配只在一個子池(subpool)中,即多個子池的使用極不均衡,導致向那個使用得最多的子池申請記憶體時失敗。報錯資訊中的"sga heap(3,0)"即指明是在第3個子池申請記憶體時失敗。本文案例中的ORA-04031錯誤其產生的原因可以歸結為Oracle對shared pool的分配/使用策略問題。
  • 作業系統記憶體不足,這隻會出現在shared pool的使用還沒有達到最大值時才會出現,並且在作業系統都有swap的情況下,只有部分作業系統才可能有這種情況,比如在HP-UX下,reserved 記憶體過多導致swap滿。
  • 其他原因,多數是因為BUG。請參考下面提及的MOS參考文件。

本文中的案例,其資料庫是執行在AIX 5.3系統中的10.2.0.4 RAC,RAC節點數為2。資料庫是從9i升級到10g,而目前處於正式升級前的測試階段。資料庫報的ORA-04031錯誤資訊如本文前面所示(其中的資料庫名稱已經做了處理)。

在繼續講解案例之前,不得不提到MOS上的幾篇關於ORA-04031錯誤的文件:

  • Master Note for Diagnosing ORA-4031 [ID 1088239.1]
  • Diagnosing and Resolving Error ORA-04031 on the Shared Pool or Other Memory Pools [Video] [ID 146599.1]
  • Interpreting the automatically generated ORA-4031 diagnostic trace. [ID 809560.1]
  • Troubleshooting and Diagnosing ORA-4031 Error [Video] [ID 396940.1]
  • ORA-4031 Common Analysis/Diagnostic Scripts [Video] [ID 430473.1]

其實分析ORA-04031錯誤,通常有以下幾個要點:

  • 判斷錯誤發生所有的記憶體區域,是shared pool,large pool還是streams pool等。這個很容易從錯誤資訊中判斷出來,本文主要描述shared pool的ORA-04031錯誤,這也是最常見的。
  • 檢查Shared Pool的總大小以及free memory的大小。如果free memory看上去挺多,以subpool為單位檢查是否存在是由於碎片導致沒有足夠的連續記憶體以供分配,特別是關注報錯資訊中提及的子池。
  • 如果Shared Pool相較於系統規模來說足夠大(通常數GB都已經是很大的了),檢查Shared Pool中有沒有佔用非常多的記憶體型別或記憶體元件,如果有,是什麼樣的型別的記憶體,在各個子池之間是否分佈均勻。如果有異常佔用較多的記憶體型別,根據此型別在MOS上搜尋是否是會有相應的BUG引起,或者分析這種型別的記憶體消耗較多的原因。比如如果是sql area很大,檢查是不是硬解析特別多,或者是不是child cursor特別多引起。
  • 基於以上分析的資料,來判斷shared pool記憶體分配失敗的原因。

上面的步驟寫得比較粗略,關於分析和解決ORA-04031問題,這裡也有一篇不錯的文章:Simplified Approach to Resolve ORA-4031

這裡關鍵的是分析Shared Pool的記憶體資料。ORA-04031錯誤發生後如果有條件可以馬上連線到資料庫中查詢相應的x$表和v$檢視得到相應的資料,否則只能透過ORA-4031錯誤發生時產生的trace檔案。_4031_dump_bitvec這個隱含引數用於控制發生ORA-04031錯誤時對SGA的dump行為,而trace檔案的分析就不像使用SQL那樣簡單了。

下面再來詳細地分析案例:
從錯誤資訊來看,很顯然,是向shared pool的第3個subpool申請記憶體時出錯。
以下的資料是shared pool的資料:

  1. SQL> select sum(bytes)/1024/1024 mb from v$sgastat where pool='shared pool';  
  2.   
  3.         MB  
  4. ----------  
  5. 4096.53062  
  6.   
  7. SQL> SELECT KSMCHCLS CLASS, COUNT(KSMCHCLS) NUM, SUM(KSMCHSIZ)   
  8.   2  SIZ,    
  9.   3  To_char( ((SUM(KSMCHSIZ)/COUNT(KSMCHCLS)/1024)),'999,999.00')|  
  10.   4  |'k' "AVG SIZE"    
  11.   5  FROM X$KSMSP GROUP BY KSMCHCLS;   
  12.   
  13. CLASS           NUM        SIZ AVG SIZE  
  14. -------- ---------- ---------- ------------  
  15. R-freea         512      24576         .05k  
  16. freeabl      807395 1643969848        1.99k  
  17. recr         530728  662065240        1.22k  
  18. R-free          256  214910976      819.82k  
  19. free          43063  100605496        2.28k  
  20. perm            140 1673368632   11,672.49k  

雖然free的數量不是太多,但是freeable的數量還是很多的。
下面是各個子池更詳細的資料:

  1. SQL> SELECT KSMCHIDX,KSMCHDUR, KSMCHCLS CLASS, COUNT(KSMCHCLS) NUM, SUM(KSMCHSIZ)   
  2.   2  SIZ,    
  3.   3  To_char( ((SUM(KSMCHSIZ)/COUNT(KSMCHCLS)/1024)),'999,999.00')|  
  4.   4  |'k' "AVG SIZE"    
  5.   5  FROM X$KSMSP GROUP BY KSMCHIDX,KSMCHDUR, KSMCHCLS  
  6.   6  order by 1,2,3;   
  7.   
  8.   KSMCHIDX   KSMCHDUR CLASS           NUM        SIZ AVG SIZE  
  9. ---------- ---------- -------- ---------- ---------- ------------  
  10.          1          1 R-free           27   22666392      819.82k  
  11.                       R-freea          54       2592         .05k  
  12.                       free             26      14024         .53k  
  13.                       perm             32  430299448   13,131.70k  
  14.                     2 R-free           12   10073952      819.82k  
  15.                       R-freea          24       1152         .05k  
  16.                       free          10531   24519112        2.27k  
  17.                       freeabl       44922   32457736         .71k  
  18.                       recr         163177  134273584         .80k  
  19.                     3 R-free            9    7555464      819.82k  
  20.                       R-freea          18        864         .05k  
  21.                       free           1678    4555704        2.65k  
  22.                       freeabl       79815  102514024        1.25k  
  23.                       recr          32689   36368096        1.09k  
  24.                     4 R-free           20   16789920      819.82k  
  25.                       R-freea          40       1920         .05k  
  26.                       free           2182    5810056        2.60k  
  27.                       freeabl       66235  254656184        3.75k  
  28.                       recr          16245   58284480        3.50k  
  29.          2          1 R-free           25   20987400      819.82k  
  30.                       R-freea          50       2400         .05k  
  31.                       free             23      20016         .85k  
  32.                       perm             35  398418384   11,116.58k  
  33.                     2 R-free            4    3357984      819.82k  
  34.                       R-freea           8        384         .05k  
  35.                       free           5137    6604176        1.26k  
  36.                       freeabl       40377   12140944         .29k  
  37.                       recr          54942   45005024         .80k  
  38.                     3 R-free            9    7555464      819.82k  
  39.                       R-freea          18        864         .05k  
  40.                       free           1477    5524568        3.65k  
  41.                       freeabl       79548  101879808        1.25k  
  42.                       recr          32380   36033448        1.09k  
  43.                     4 R-free           21   17629416      819.82k  
  44.                       R-freea          42       2016         .05k  
  45.                       free           2540    7092424        2.73k  
  46.                       freeabl       70133  270332800        3.76k  
  47.                       recr          15924   57263032        3.51k  
  48.          3          1 R-free           26   21826896      819.82k  
  49.                       R-freea          52       2496         .05k  
  50.                       free             26      20520         .77k  
  51.                       perm             33  414355416   12,261.94k  
  52.                     2 R-free            4    3357984      819.82k  
  53.                       R-freea           8        384         .05k  
  54.                       free           4693    7053032        1.47k  
  55.                       freeabl       49723   14339800         .28k  
  56.                       recr          52771   42357312         .78k  
  57.                     3 R-free           11    9234456      819.82k  
  58.                       R-freea          22       1056         .05k  
  59.                       free           3594    9280904        2.52k  
  60.                       freeabl       95823  121934488        1.24k  
  61.                       recr          39643   44097504        1.09k  
  62.                     4 R-free           25   20987400      819.82k  
  63.                       R-freea          50       2400         .05k  
  64.                       free           2822    7291680        2.52k  
  65.                       freeabl       84443  323149712        3.74k  
  66.                       recr          19148   67997008        3.47k  
  67.          4          1 R-free           27   22666392      819.82k  
  68.                       R-freea          54       2592         .05k  
  69.                       free             26      18088         .68k  
  70.                       perm             40  430295384   10,505.26k  
  71.                     2 R-free            6    5036976      819.82k  
  72.                       R-freea          12        576         .05k  
  73.                       free           4818   11473920        2.33k  
  74.                       freeabl       46089   39963224         .85k  
  75.                       recr          54061   44188072         .80k  
  76.                     3 R-free            9    7555464      819.82k  
  77.                       R-freea          18        864         .05k  
  78.                       free           1427    4109504        2.81k  
  79.                       freeabl       80026  102379080        1.25k  
  80.                       recr          33217   36949240        1.09k  
  81.                     4 R-free           21   17629416      819.82k  
  82.                       R-freea          42       2016         .05k  
  83.                       free           1993    6228464        3.05k  
  84.                       freeabl       70581  269087136        3.72k  
  85.                       recr          16614   59372656        3.49k  

KSMCHDUR是什麼意思?在9i裡面這個列的值通常為1。實際上,Oracle從9i開始,將shared pool劃分為多個sub pool。而在10g以上的版本中(具體開始的版本號已經不記得),每個sub pool又分了4個更小的池,我們暫且稱之為mini heap。每個mini heap有其自己的free list。KSMCHDUR這一列即表示mini heap的編號。"heap(3,0)"中的0是指第1個mini heap。

在上面的資料中,可以看到這個子池的第1個mini heap的free已經很少,只有10來K。另外,我們可以觀察到,perm型別的記憶體塊只存在於每個sub pool的第1個min heap中。這個是一個重點,在後面會有解釋。

這裡本應該有透過查詢v$sgastat得到shared pool的各個元件佔用的記憶體分佈,只是寫BLOG時找不到了....但是我們可以在trace檔案中找到資料,下面只列出sub pool 3的資料:

  1. ==============================  
  2. Memory Utilization of Subpool 3  
  3. ================================  
  4.      Allocation Name          Size     
  5. _________________________  __________  
  6. "free memory              "    81466568    
  7. "miscellaneous            "           0    
  8. "dpslut_kfdsg             "         512    
  9. "trace buffer             "      737280    
  10. "trace_knlasg             "         504    
  11. "gcs res hash bucket      "     1048576    
  12. "gcs res latch table      "       12288    
  13. "evaluation con           "           0    
  14. "sql area                 "   344545752    
  15. "UNDO STAT INFO           "       59904    
  16. "txncallback              "      141744    
  17. "transaction              "     2103264    
  18. "ges resource pools       "        3968    
  19. "sessions                 "     4526488    
  20. "dlo fib struct           "      128032    
  21. "KJCTS process batching st"         240    
  22. "row cache                "        3272    
  23. "KCB where statistics arra"       25888    
  24. "KCB buffer wait statistic"       32000    
  25. "KCB incremental ckpt entr"         512    
  26. "invalid low rba queue    "        1024    
  27. "table definiti           "      108704    
  28. "temporary tabl           "        4136    
  29. "KCL instance cache transf"      131072    
  30. "resumable                "        2720    
  31. "KESTB existence bitvec se"         128    
  32. "type object de           "      392448    
  33. "enqueue_hash             "      318960    
  34. "KSXR pending consumption "       20192    
  35. "KTI SGA freeable small po"           0    
  36. "trigger defini           "      885472    
  37. "trigger source           "       99264    
  38. "trigger inform           "         960    
  39. "KTCN: Obj Invalidation Se"        2336    
  40. "kmgsb circular statistics"      108800    
  41. "kgl lock hash table state"       45360    
  42. "kglsim size of pinned mem"        8024    
  43. "kelr system metrics table"         280    
  44. "kzctxgjsi ksuseclid memor"      117360    
  45. "kzctxgjci ksuseclid  memo"           0    
  46. "CCursor                  "    95912048    
  47. "ksr message pool free que"      188960    
  48. "ksb ci process list (each"         144    
  49. "ksunfy: nodes of hierarch"         320    
  50. "ksuloi: long op free list"         256    
  51. "kwqmncal: allocate buffer"        4048    
  52. "ksim group query request "           0    
  53. "ksuxds ksuseclid  memory "           0    
  54. "call                     "       87304    
  55. "dictionary cache         "           0    
  56. "KSXR pending reply queue "      255488    
  57. "hng: All sessions data fo"           0    
  58. "ksfv subheap descriptor  "         184    
  59. "gcs resources            "   169082312    
  60. "gcs affinity             "        8320    
  61. "gcs opaque in            "       12312    
  62. "PCursor                  "    50743128    
  63. "ges resource             "      539376    
  64. "fdrec_kffsg              "          24    
  65. "work area tab            "       80640    
  66. "kglsim main lru count    "       38400    
  67. "plwpil:wa                "        4264    
  68. "grptab_kfgsg             "        2464    
  69. "AW SGA                   "          40    
  70. "KEWS sesstat seg tbl     "           8    
  71. "kebm slave descriptors   "        1456    
  72. "kglsim hash table bkts   "     1048576    
  73. "KSXR global channels     "        1288    
  74. "ges enqueues             "    17333720    
  75. "PLS chunk                "         352    
  76. "KSQ event description    "        1440    
  77. "KESTB existence bitvec   "        4096    
  78. "gcs shadows              "   101246344    
  79. "qmtb_init_data           "         224    
  80. "Core dump directory      "         264    
  81. "sort segment handle      "        7480    
  82. "SERVICE NAME ENTRY       "          48    
  83. "PQ/BizCard               "        1536    
  84. "qtree_kwqbspse           "          40    
  85. "latch descriptor table   "        1576    
  86. "recovery domain          "       29856    
  87. "parameters               "       30056    
  88. "SHARED SERVERS INFO      "         240    
  89. "qtree_kwqbsgn            "          40    
  90. "post agent               "           0    
  91. "pspool_kfsg              "          80    
  92. "plwsppwp:wa              "           0    
  93. "PL/SQL DIANA             "    14050624    
  94. "segmented arrays         "        2072    
  95. "Checkpoint queue         "     4097024    
  96. "sim lru segments         "        2560    
  97. "sim segment hits         "        2560    
  98. "sim state object         "          40    
  99. "partitioning d           "      199616    
  100. "ASH buffers              "     8388608    
  101. "message pool freequeue   "      276336    
  102. "PL/SQL MPCODE            "     4499360    
  103. "PL/SQL PPCODE            "     3984944    
  104. "procs: ksunfy            "     1512000    
  105. "primem_kfmdsg            "        1032    
  106. "SYSTEM PARAMETERS        "       76624    
  107. "object queue hash buckets"      262656    
  108. "object queue hash table d"        7552    
  109. "object level stats hash t"         512    
  110. "object stat dummy statprv"         144    
  111. "sim cache sizes          "         320    
  112. "logout storm management  "       24000    
  113. "pl/sql source            "       21256    
  114. "sys event stats          "      199136    
  115. "parameter handle         "       67896    
  116. "Parameter Handle         "        1656    
  117. "channel handle           "      828672    
  118. "API blockers array       "          64    
  119. "PARAMETER TABLE          "        2048    
  120. "PARAMETER ENTRY          "           8    
  121. "LGWR post requested array"          24    
  122. "bloom filter             "        3104    
  123. "param hash values        "        5984    
  124. "sql area:PLSQL           "    11477776    
  125. "PX subheap desc          "         256    
  126. "repository               "      213544    
  127. "sql area:KOKA            "       16192    
  128. "archive_lag_target       "        9624    
  129. "state objects            "         640    
  130. "latch nowait fails or sle"      116832    
  131. "sched job slv            "        5952    
  132. "pso tbs: ksunfy          "      390000    
  133. "dummy                    "      269928    
  134. "Sort Segment             "       37440    
  135. "Cursor Stats             "     6095760    
  136. "Banner Storage           "        2048    
  137. "quiescing session        "        3872    
  138. "API data buffer          "          16    
  139. "buffer handles           "     1020000    
  140. "prmtzdini tz region      "      408320    
  141. "sga node map             "          16    
  142. "savepoints               "           0    
  143. "Managed Standby Proc Arra"       24576    
  144. "OS proc request holder   "        4664    
  145. "db_files                 "      416576    
  146. "PX server msg stats      "        2288    
  147. "KQR M PO                 "      283376    
  148. "kks stats                "          40    
  149. "parameter table block    "      483168    
  150. "KSFV SGA                 "         824    
  151. "plugin datafile array    "       36016    
  152. "plwda:PLW_STR_NEW_RVAL   "          24    
  153. "plwspv:PLW_STR_NEW_VAL   "          16    
  154. "KGKP sga                 "          32    
  155. "BRANCH TABLE SEGMENTED AR"       70176    
  156. "mvobj part des           "      306544    
  157. "parameter value memory   "         216    
  158. "multiblock re            "       98496    
  159. "parameter text value     "        1080    
  160. "parallel_max_servers     "        8192    
  161. "KGLS heap                "    13290800    
  162. "KGSKI sga                "          80    
  163. "resize request state obje"      368000    
  164. "MTTR advisory            "     1462832    
  165. "monitoring co            "       12480    
  166. "rules engine aggregate st"        1416    
  167. "krbmror                  "       36400    
  168. "joxs heap                "         136    
  169. "krbmrsr                  "         152    
  170. "ksfqpar                  "        4008    
  171. "SGA - SWRF DrvMet Runtime"        2656    
  172. "SGA - SWRF Metrics ksuTim"          72    
  173. "SGA - SWRF RawMet Runtime"        1408    
  174. "SGA - SWRF Metrics WCTime"          32    
  175. "SQL Memory Manager Base W"       13400    
  176. "change notification regis"        4096    
  177. "simulator latch/bucket st"       59392    
  178. "Prefetch history buffer  "        2832    
  179. "change notification obj m"        4096    
  180. "KQR ENQ                  "       16512    
  181. "kksss                    "       16464    
  182. "API data buffer length   "           0    
  183. "kokcd                    "           0    
  184. "kohsg                    "           8    
  185. "Sequence Background Insta"          88    
  186. "ksfqpn                   "         416    
  187. "KGLS SP                  "        4704    
  188. "knstsg                   "          48    
  189. "latch classes            "         352    
  190. "system default language h"         568    
  191. "name-service entry       "        2592    
  192. "API data buffer array    "           0    
  193. "kzull                    "        4096    
  194. "kzulu                    "         392    
  195. "kfgsga                   "         104    
  196. "library cache            "    46604712    
  197. "kcrrny                   "       25320    
  198. "spfile cleanup structure "       16760    
  199. "xssinfo                  "        5952    
  200. "buffer_pool_desc_array   "        3384    
  201. "row cache child latch    "        3360    
  202. "rm request queue link    "        5320    
  203. "SCHEDULING POLICY TABLE  "         160    
  204. "namhsh_kfdsg             "        4104    
  205. "Closed Thread SCN Bitvec "        8448    
  206. "Client ID trace settings "        3872    
  207. "osp allocation           "       21104    
  208. "os statistics            "        9192    
  209. "plwppwp:PLW_STR_NEW_LEN_V"          16    
  210. "plwgc: plwgc_garbage_clea"           0    
  211. "plwiiw: kglpql warnings  "           0    
  212. "object queue             "      808080    
  213. "obj stat memo            "      599184    
  214. "obj htab chun            "      122960    
  215. "object level             "      111888    
  216. "XCT XGA                  "           0    
  217. "SGA - SWRF Metric Eidbuf "      900840    
  218. "Processor group descripto"          64    
  219. "Prefetch client count per"          32    
  220. "X$SKGXPIA                "        2680    
  221. "simulator hash buckets   "     2101248    
  222. "State object subpools    "         896    
  223. "API data buffer length ma"           0    
  224. "AWR Table Info (KEW layer"         872    
  225. "character set memory     "        4856    
  226. "sim segment num bufs     "        1280    
  227. "character set object     "      129728    
  228. "session idle latches     "        2560    
  229. "qesmmaInitialize:        "         112    
  230. "returns from remote ops  "       49152    
  231. "name-service             "        4080    
  232. "SGA - SWRF Metric CHBs   "       10912    
  233. "listener addresses       "          32    
  234. "db_block_hash_buckets    "    67108864    
  235. "KSI resource types       "        2704    
  236. "kglsim object batch      "     4196304    
  237. "trigger condition node   "          72    
  238. "ksws service events      "       18560    
  239. "Heap0: KGL               "    11642128    
  240. "fixed allocation callback"         392    
  241. "kqlpWrntoStr:value       "           0    
  242. "KEWS statistic name      "         424    
  243. "KEWS statistic maps      "        1096    
  244. "KCL partition table      "      131072    
  245. "kebm slave message       "          88    
  246. "kcbl state objects       "       12800    
  247. "free rm request queue lin"           0    
  248. "xsoqsehift               "        3104    
  249. "DBWR event stats array   "         192    
  250. "kgllk hash table         "      659456    
  251. "event descriptor table   "         192    
  252. "kpssnfy: kpsssgct        "          32    
  253. "kpscad: kpscscon         "        1952    
  254. "dbwriter coalesce buffer "     3158016    
  255. "kglsim hash table        "        8208    
  256. "gcs resource freelist dyn"         256    
  257. "gcs shadow locks dyn seg "         256    
  258. "kks stats latch          "         160    
  259. "KTC latch cleanup        "         576    
  260. "ges enqueue max. usage pe"          64    
  261. "ges lmd process descripto"        2760    
  262. "KTU latch cleanup        "        2496    
  263. "kscdnfyinithead          "          16    
  264. "X$KSVIT table            "         512    
  265. "kqlpaac:value-1          "          64    
  266. "KCL buffer header        "      192064    
  267. "kxfpdp pointers          "       28800    
  268. "kodosgi kopfdo           "         104    
  269. "kglsim latches           "         136    
  270. "TXN TABLE SEGMENTED ARRAY"       54784    
  271. "KJCT remote i            "        1640    
  272. "KKJ SHRD WRQS            "         288    
  273. "KJC dest ctx             "        3560    
  274. "kwrsnfy: kwrs            "        1624    
  275. "kwqmn:tskdata            "           0    
  276. "KKKI consumer            "        4136    
  277. "dbwr suspend/resume ptr a"          16    
  278. "dbwr actual working sets "          64    
  279. "KGSKI schedule           "           0    
  280. "temp lob duration state o"        3296    
  281. "ges regular msg buffers  "     3078008    
  282. "jsksncb: 9               "       28672    
  283. "Transportable DB Converte"        2552    
  284. "KTU lat struct           "         800    
  285. "kks stats hds            "         256    
  286. "KSFD SGA I/O b           "     4190248    
  287. "HTTP fixed headers       "          72    
  288. "UNDO INFO SEGMENTED ARRAY"      649856    
  289. "ges process hash table   "      132000    
  290. "jsksncb-latch            "        1280    
  291. "kfkid hrec               "          24    
  292. "KTCCC OBJECT             "           0    
  293. "KTPR HIST TB             "        2808    
  294. "KTF MAPPINGS             "       12288    
  295. "kksss-heap               "       35136    
  296. "kglsim heap              "     3431232    
  297. "event statistics per sess"     7665280    
  298. "eventlist to post commits"          16  

從上面的資料可以看到,第3個sub pool中,佔用較多的記憶體是gcs resources、gcs shadows以及sql area。但是沒有明顯的異常。
下面是第3個sub pool中第1個mini-heap中free memory的更詳細資料:

  1. SQL> break on ksmchidx on ksmchdur  
  2. SQL> select  
  3.   2    ksmchidx,ksmchdur,  
  4.   3    case  
  5.   4          when ksmchsiz < 1672 then trunc((ksmchsiz-32)/8)  
  6.   5          when ksmchsiz < 4120 then trunc((ksmchsiz+7928)/48)  
  7.   6          when ksmchsiz < 8216 then 250  
  8.   7          when ksmchsiz < 16408 then 251  
  9.   8          when ksmchsiz < 32792 then 252  
  10.   9          when ksmchsiz < 65560 then 253  
  11.  10          when ksmchsiz >= 65560 then 253  
  12.  11     end bucket,  
  13.  12    sum(ksmchsiz)  free_space,  
  14.  13    count(*)  free_chunks,  
  15.  14    trunc(avg(ksmchsiz))  average_size,  
  16.  15    max(ksmchsiz)  biggest  
  17.  16  from  
  18.  17    sys.x$ksmsp  
  19.  18  where  
  20.  19    inst_id = userenv('Instance'and  
  21.  20    ksmchcls = 'free'  
  22.  21  group by  
  23.  22    case  
  24.  23          when ksmchsiz < 1672 then trunc((ksmchsiz-32)/8)  
  25.  24          when ksmchsiz < 4120 then trunc((ksmchsiz+7928)/48)  
  26.  25          when ksmchsiz < 8216 then 250  
  27.  26          when ksmchsiz < 16408 then 251  
  28.  27          when ksmchsiz < 32792 then 252  
  29.  28          when ksmchsiz < 65560 then 253  
  30.  29          when ksmchsiz >= 65560 then 253  
  31.  30     end ,  
  32.  31    ksmchidx, ksmchdur  
  33.  32  order by ksmchidx , ksmchdur  
  34.  33  /  
  35.   
  36.   KSMCHIDX   KSMCHDUR     BUCKET FREE_SPACE FREE_CHUNKS AVERAGE_SIZE    BIGGEST  
  37. ---------- ---------- ---------- ---------- ----------- ------------ ----------  
  38.          3          1          5         72           1           72         72  
  39.                               13        136           1          136        136  
  40.                               27        248           1          248        248  
  41.                               48        416           1          416        416  
  42.                               56       1920           4          480        480  
  43.                               66       1680           3          560        560  
  44.                               68       4608           8          576        576  
  45.                              164       1344           1         1344       1344  
  46.                              180       1472           1         1472       1472  
  47.                              188       1536           1         1536       1536  
  48.                              190       1552           1         1552       1552  
  49.                              199       1624           1         1624       1624  
  50.                              204       1880           1         1880       1880  
  51.                              207       2032           1         2032       2032  

可以看到,最大的free memory塊才2032位元組,而報錯中提到的申請的記憶體大小為4128位元組。由於在第3個sub pool的第1個mini heap中沒有4128位元組的連續free memory,所以導致記憶體申請失敗。

那麼這裡的問題是,為什麼這個mini heap中的free memory那麼少?正如前面提及,為什麼這個mini heap中的已經使用的型別全是perm型別?這個問題的答案就在於"DURATION"。Oracle在啟用了SGA自動管理的模式下,為了便於在shared pool與buffer cache或其他記憶體之間動態調整大小,規定了在每一個mini heap中分配記憶體按照duration來進行。這裡duration可以理解為記憶體塊的持久時間。perm型別的記憶體塊,就是分配後不能釋放,只能用於相同元件的重用。比如gcs resources這種元件的記憶體是perm型別,這種記憶體被分配後,不能釋放給sql area使用,也不能給gcs shadows使用,只能給其他的gcs resource使用。按DURATION分配記憶體時,perm型別的記憶體就只能從每個sub pool的第1個mini heap中分配。而其他型別的記憶體通常在sub pool的第2-4個mini heap中分配。由於perm型別的記憶體不能釋放,也不能被其他元件的記憶體重用,所以裡面的記憶體會越用越少,如果沒有了free memory怎麼辦?前面說到,這種模式主要是工作在SGA自動管理模式下,如果free memory沒有了,就會從SGA中的其他部分,比如buffer cache中取得memory chunk,加入到缺少記憶體的mini heap中。正常情況下這種機制沒有問題。

完全使用SGA自動管理有一個缺陷就是,如果應用系統繫結變數做得不好,或者由於BUG,child cursor過多,導致shared pool會變得很大,甚至超過10G,嚴重的比buffer cache還大,另一方面,在buffer cache和shared pool之間頻繁地調整大小,可能會導致嚴重的解析問題和其他效能問題。針對這個問題,通常有2種解決辦法:一種就是關閉SGA自動管理,即將SGA_TARGET設定為0,以9i的方式來設定shared_pool_size,db_cache_size這些引數,來手動管理SGA;第二種就是sga_target仍然大於0,即自動管理SGA,但是透過設定shared_pool_size,db_cache_size等引數限制這些記憶體元件的最小大小,而只留給系統極少的自動調整空間。

而出現問題的這套系統,正是使用了第二種方式,開啟了SGA自動調整,但是留給自動調整的空間極少。SGA_TARGET為35G,buffer_cache_size為30G,shared_pool_size為4G,再加上large_pool等元件,幾乎沒有什麼可自動調整的餘地。這種方式下,就存在了問題。下面來做一個按時間的分析:

  1. 時間T1,資料庫啟動,shared pool只消耗了極少量的記憶體。
  2. 時間T2至時間T3,Oracle程式請求shared pool記憶體,Oracle會向作業系統以指定的粒度為單位(比如16MB)請求實體記憶體,加入到所請求記憶體所在的mini heap中。直至shared pool的大小達到shared pool最大容許的大小。這個容許大小由各引數計算而來。比如說SGA_TARGET為10G,其他元件的引數設定後最小值為8G,shared_pool_size的值為1G,但是shared pool的最大容許大小為2G。這個時候,每個sub pool的mini heap的大小已經固定。在到達shared pool最大容許大小這一階段,可能會從buffer cache等元件中佔用。
  3. 時間T4,Oracle程式請求shared pool記憶體,這個時候只能從free list或age out記憶體塊後獲取記憶體,對於sub pool的第1個mini heap,只能從free list中獲取,因為這個mini heap中的已用記憶體全是perm,是不能age out的。
  4. 時間T5,Oracle程式請求shared sub pool中第1個mini heap的記憶體,但是free list中已經沒有記憶體。所以報ORA-04031錯誤。

在上面的時間點T5那裡,如果SGA有較大的自動調整空間,比如說完全沒有限制,即buffer_cache_size等引數很少或為0,這樣在請求第1個mini heap中的記憶體時,完全可以從buffer cache中佔用,這樣的後果是使shared pool越來越大。

而本文案例的ORA-04031,正是由於SGA自動管理,而自動調整的餘地又太小,最終使sub pool的第1個mini heap空間用光。當然我們可以分析為什麼會用光,這個就顯得更為複雜,這跟資料量、應用系統都有很大的關係。而系統中第1次出現ORA-04031錯誤的程式,是一個job程式,而此後大部分出現的錯誤均是job程式,能檢查job程式碼,發現在做大量的表的大量資料的UPDATE操作,這可能是引起gcs shadows和gcs resources大量記憶體使用的原因。在一套RAC資料庫中,gcs和ges相關的perm記憶體佔用可能會比較大。

那麼除了調整應用,應該怎麼樣解決這樣問題?這裡的解決方法是增加shared_pool_size引數到6G,同時將sga_target設定為0,再重啟。
而另一種可能的辦法是將引數“_enable_shared_pool_durations"設定為FALSE。這一引數為FALSE,將會使shared pool記憶體分配時,不再使某一型別的記憶體(比如perm)必須要求在一個固定的mini heap中。而實際上,sga_target設定為0之後,這一個引數自動會設為FALSE(由於這一引數是靜態引數,所以修改了sga_target之後需要重啟才會使這個隱含引數改變),所以建議的解決辦法是設定sga_target引數,而不建議修改隱含引數。當然還有一種辦法是完全讓Oracle自動管理SGA,將buffer_cache_size和shared_pool_size等引數設定為0,但是正如前面所說,這種方法有比較大的缺陷。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28211342/viewspace-2130968/,如需轉載,請註明出處,否則將追究法律責任。

相關文章