前不久某客戶的一套核心資料庫(10.2.0.4.12),據說每間隔一段時間就必須重啟,因為會報ORA-04031錯誤。查詢發現shared pool差不多5G的樣子,其實ges resource消耗了差不多3.5G shared pool 記憶體,也確實有些離譜了。
SQL> c/gcs/ges
1* select * from v$sgastat where name like 'ges%'
SQL> /
我們可以看到,ges resource消耗的記憶體確實非常高。那麼這裡為什麼ges resource 消耗的記憶體這麼高呢?
通過檢查v$resource_limit發現存在有些異常,如下所示:
RESOURCE_NAME CURRENT_UTILIZATION MAX_UTILIZATION INITIAL_ALLOCATION LIMIT_VALUE
-------------------- ------------------- --------------- -------------------- -------------
ges_procs 181 439 1001 1001
ges_ress 0 0 27462 UNLIMITED
ges_locks 0 0 40358 UNLIMITED
ges_cache_ress 8559179 14625461 0 UNLIMITED
ges_reg_msgs 243 898 2750 UNLIMITED
ges_big_msgs 41 35280 1934 UNLIMITED
ges_rsv_msgs 0 0 1000 1000
SQL> select startup_time from v$instance;
STARTUP_TIME
-------------------
2015-10-26 05:02:04
我們可以發現,ges_cache_ress 的max 和 current 都很大。大的超乎想象。從現象來看,可以大致判斷是shared pool中cache的 ges resource沒有及時回收,導致ges resource佔據的記憶體比較大。
想到這裡,我心中產生了一個疑問,是否Oracle 有相關隱含參數來控制這個資源回收的機制呢?我們知道Oracle 通常都是這麼乾的,通過隱含參數來控制某項功能或機制。
搜下發現了2個相關的bug,確實可能出現ges resource 消耗記憶體很高的情況,最後產生ora-04031錯誤。
其中文檔中提到了一個參數_lm_cache_res_cleanup;通過調整該參數,來該表ges resource的回收機制;有可能避免這個情況。
方法好用不,要試試才知道,果斷告知客戶進行調整,然後觀察幾天后,發現似乎ges resource的記憶體消耗得到了有效控制:
SQL> select * from v$sgastat where name like '%ges res%';
POOL NAME BYTES
------------------------ ----------------------------- ----------
shared pool ges resource hash seq tab 32768
shared pool ges res mastership bucket 4096
shared pool ges resource pools 1984
shared pool ges reserved msg buffers 8240008
shared pool ges resource 215312592
shared pool ges resource hash table 1441792
6 rows selected.
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
Session altered.
SQL> select startup_time from v$instance;
STARTUP_TIME
-------------------
2016-01-28 23:08:27
SQL> select sysdate from dual;
SYSDATE
-------------------
2016-02-03 10:24:17
有些人可能會說,才幾天可能看不出來吧?實際上,之前客未調整之前,重啟執行個體才1天,ges resource就超過300M了。
備忘: bug 9026008,bug 10042937 跟該參數有關係,影響版本為11.1,11.2部分版本,大家可以閱讀下。