聊聊Oracle共享池的Duration機制
ORA-4031問題是我們這代DBA經常會面對的靈魂拷問。每當出現問題,用戶都會問幾個問題:“為什么會出問題?”、“問題出在什么地方了?”、“為什么共享池還有那么多空閑,就4031了”、“下回如何避免類似問題發生?”。基于Oracle復雜的共享池結構和用戶千差萬別的應用場景。想要好好回答出這些問題并不容易。對于二十多年前的那些DBA來說,ORA-4031問題也是督促他們認真學習Oracle Internal技術的主因之一。
Oracle的共享池從問世開始這幾十年來,一直是十分考驗DBA能力的存在,這涉及到Oracle內存堆HEAP的管理(KGL)算法問題、SQL解析問題、SQL共享問題、并發控制問題等多個領域。共享池出問題后分析與處理的復雜程度,如果沒有經歷過,絕對是不敢想象的。
閱讀SHARED POOL HEAP DUMP是很多那個時代DBA都必須具備的能力。共享池是Oracle解決超高并發問題的關鍵,為了讓共享池更加高效同時管理更加簡單,Oracle不斷地在優化其算法,甚至對復雜的數據結構做了多次調整。從最初把LARGE POOL采用獨立的鏈表、留出獨立的空閑空間Reserved Pool用于大內存分析,到9i開始引入的SubPool,都是為了讓共享池更加高效并發,并且盡可能少出問題。自從10g引入了ASMM,并且服務器的物理內存越來越便宜之后,共享池出大問題,在業務高峰期影響業務系統運行的問題才少了很多。Oracle 11g之后,隨著共享池管理的再優化,再加上針對cursor mutex的各種優化,DBA才離ORA-4031更遠了一些。
關于Oracle的共享池的SUBPOOL的問題,大家討論得比較多,大多數認真學習過OCP教材的朋友都爛熟于心了,今天不再討論。有時候共享池太大,分成了多個SUBPOOL,如果碎片化比較嚴重,那么出現分配較大的CHUNK的時候,就很容易出現ORA-4031。不過有些時候好像有些時候每個SUBPOOL里好像也有充足的空閑空間,照樣報ORA-4031,而且刷共享池都解決不了問題,必須重啟數據庫才行。
似乎我們所掌握的知識還不足以解釋某些特殊的情況,一般遇到這種情況,我會認為一定是有我們所還沒有掌握的一些技術細節讓我們無法繼續向下分析。今天我給大家科普一個小常識,subpool下面還有一層subpool,也就是官方所說的durations。當Oracle數據庫啟用AMM/ASMM的時候,shared sub pool會根據預期需要的持續時間對分配的內存進行分類,將SUBPOOL分成4個durations。4個分區分別是:
lduration 0 (instance):實例級的永久性內存,只有實例shutdown才會釋放。該部分內存無法通過flush shared pool等手段釋放。包括:參數表、kgsp-heap,kglsim object batch等實例數據結構。
lduration 1:session
lduration 2:cursor
lduration 3:execution
圖片
每個duration都是一個單獨的存儲桶,當內存分片分配給duration時,該分片中的內存不可用于子池中的任何其他duration。已經分配給duration的分片內存移動到另一duration的唯一方法是根據需要將分片轉移到緩沖區緩存,然后返回共享池,不過這種情況實際上很少發生。因此分配給duration的granules通常會停留在那里。如果在較大的分片上分配較小的內存,可能導致大部分空閑內存未被使用,并且不可用于任何其他duration。這會增加共享池出現ORA-4031的機會。
圖片
上面是一個Oracle 11.2.0.4的shared pool heap dump,其中sga heap(1,0)表示這是SUBPOOL1的duration 0的dump。我們可以看到在這個dump中顯示duration是開啟的。
將subpool再劃分為多個duration會加大共享池碎片化的程度。特別是當duration 0無內存可分配時,哪怕其他duration還有很多空間,也無法再擴充空間,此時產生宕機的機會很大。Oracle提供了一個隱含參數來開啟duration,默認情況,這個參數是true。通過設置"_enable_shared_pool_durations"=false可以關閉duration功能。不過要關閉duration要考慮清楚,因為perment空間可能會在關閉duration后 快速增長,導致必須重啟數據庫實例才能完全釋放。甚至有些時候需要在重啟實例前在spfile中去掉”__shared_pool_size”參數,確保實例啟動后ASMM合理分配共享池的空間。
圖片
Oracle 12.1之后,duration機制做了優化,0,1,2三個duration被合并為一個,只保留了0,3兩個duration,這樣的話出現因為內存使用不均勻而導致的ORA-4031被大大減少了。這個功能被backport到了11.2.0.2以后的版本中,被ORA-4031引發宕機困擾的11G用戶,可以通過打補丁8857940來擺脫煩惱了。
今天和大家分享了Oracle shared pool duration的一些基本概念,希望大家遇到類似問題的時候,這篇文章能有所幫助。其實從Oracle 共享池subpool和duration的變遷,是不是也看出一個好的數據庫產品不大可能被設計出來,而是要在用戶場景中千錘百煉才能變得越來越好呢?