獲取 ORA-04031 後調整 Java 池
我在 Windows 2012 RC2 上執行 Oracle 12.2.0.1 標準版。我沒有執行 Oracle 的自動記憶體管理。
我們在警報日誌中看到了這些:
ORA-04031: unable to allocate 4096 bytes of shared memory ("java pool","prv//////LBKLAGIMAAAAAAAA","JOXLE^aff7380e",":SGAClass")
我想嘗試的第一件事是刷新共享池以解決眼前的問題,而開發團隊正在修復 SQL 程式碼,所以我執行:
ALTER SYSTEM FLUSH SHARED_POOL;
直到那時我才意識到 Java 池實際上並不是共享池的一部分。所以我試著看一下Java池。
我想這告訴我我的 Java 池大約是 32MB:
SQL> select * from v$javapool;
CATEGORY MEMUSED CON_ID ------------------------------------------------ ---------- ---------- :Intern 973440 0 :SGAClass 32103240 0 :SROState 81120 0
我執行了這個調整工具,如果我能正確解釋的話,它說增加 Java 池大小並沒有太多好處:
select estd_lc_size, java_pool_size_for_estimate, java_pool_size_factor from v$java_pool_advice;
ESTD_LC_SIZE JAVA_POOL_SIZE_FOR_ESTIMATE JAVA_POOL_SIZE_FACTOR ------------ --------------------------- --------------------- 8 16 .5 24 32 1 25 48 1.5 25 64 2 25 80 2.5 25 96 3 25 112 3.5 25 128 4 25 144 4.5 25 160 5 25 176 5.5
我從這裡的 Oracle 文件中執行了以下查詢,它似乎表明 SGA_TARGET 值很好!
SELECT ( (SELECT SUM(value) FROM V$SGA) - (SELECT CURRENT_SIZE FROM V$SGA_DYNAMIC_FREE_MEMORY) ) "SGA_TARGET" FROM DUAL;
SGA_TARGET ---------- 5167382528 = 4928 MB i.e. same as what it currently is!
我知道:
MEMORY_TARGET = 0 SGA_MAX_SIZE = 4928M SGA_TARGET = 4928M JAVA_POOL_SIZE = 0 SHARED_POOL_SIZE = 0 DB_CACHE_SIZE = 0 DB_KEEP_CACHE_SIZE = 0 MEMORY_MAX_TARGET = 0
…所以當我們不使用 AMM 時,我有點困惑如何調整它。
那麼如何解決這個問題呢?
- 是增加 Java 池大小的最佳選擇嗎?
- 如果是這樣,不使用 AMM 時如何執行此操作?
AMM 還是 ASMM?
Oracle 數據庫實例中有兩種形式的記憶體管理:
- 自動記憶體管理 (AMM)
- 自動共享記憶體管理 (ASMM)
如果您要為 設置值,
MEMORY_MAX_TARGET
那麼MEMORY_TARGET
您將處於 AMM 模式。您的 Oracle 實例將分配記憶體直到MEMORY_TARGET
設置。如果您注意到性能影響,那麼您可以將MEMORY_TARGET
值增加到MEMORY_MAX_TARGET
大小,而無需重新啟動實例。如果您還沒有為您的實例設置
MEMORY_MAX_TARGET
和MEMORY_TARGET
值,那麼我們可以假設您處於 ASMM 模式,因為您已經為SGA_TARGET
參數設置了一個值。在 ASMM 模式下,會自動配置以下參數:
表 6-2 自動調整大小的 SGA 組件及對應參數
SHARE_POOL_SIZE
LARGE_POOL_SIZE
JAVA_POOL_SIZE
DB_CACHE_SIZE
STREAMS_POOL_SIZE
參考: 表 6-2 (Oracle 文件)
還有以下小註釋表明:
除了設置
SGA_TARGET
為非零值之外,您還必須將表 6-2 中列出的所有初始化參數設置為零,以啟用自動調整大小的 SGA 組件的全自動調整。因此無需將 設置為
JAVA_POOL_SIZE
非零值,除非您想手動為參數分配最小值。否則,Oracle 將在您的大小邊界內分配記憶體SGA_TARGET
,目前略高於 4 GB (4928M
)。什麼在使用 SGA_TARGET?
然後有提示:
(強調我的)
表 6-3中列出的手動調整大小的參數,如果已設置,則從 中獲取它們的記憶體
SGA_TARGET
,留下可用於表 6-2 中列出的組件的內容。表 6-3中的參數為:
LOG_BUFFER
DB_KEEP_CACHE_SIZE
DB_RECYCLE_CACHE_SIZE
DB_nK_CACHE_SIZE
參考: 表 6-3(Oracle 文件)
解決方案
如果表 6-3中的組件使用了太多記憶體,則池中沒有足夠的記憶體來自動為表 6-2中的組件或在您的情況下為參數
SGA_TARGET
分配足夠的記憶體。您可以觀察錯誤:JAVA_POOL_SIZE
ORA-04031: 無法分配 4096 字節的共享記憶體 (“java pool”,“prv//////LBKLAGIMAAAAAAAAA”,“JOXLE^aff7380e”,":SGAClass")
您可能必須將
SGA_TARGET
參數增加到比您目前擁有的值更高的值,以便 SGA 池有足夠的記憶體來自動調整動態參數。嘗試
8192M
觀察您的 Oracle 實例如何響應這些更改。參考閱讀
- 6.4.2.4.1 SGA 目標和自動調整大小的 SGA 組件(Oracle Docs | 12.2 | Admin Guide)
- 6.4.2 使用自動共享記憶體管理(Oracle Docs | 12.2 | Admin Guide)
- 6.3 使用自動記憶體管理(Oracle Docs | 12.2 | Admin Guide)