DBAplus社羣 | 2016-04-14 20:31html
1概述算法
Oracle發展這麼多年,提供了多種的內存管理方式,從最先SGA、PGA手工管理,到9I版本出現的PGA的自動管理,到10G版本出現的SGA自動管理(ASMM),再到11G版本出現的memory自動管理(AMM),Oracle基本是在朝着智能化、傻瓜化、自動化的方向穩步前進着,對於初學Oracle的DBA來講,看到這些不一樣的內存管理方式必定內心有着不一樣程度的疑惑,例如:數據庫
Oracle有這麼多內存分配的管理方式,我該使用哪種?是使用11G版本推出的AMM管理方式,仍是使用10G版本出現的ASMM管理方式?或者乾脆使用最舊的手工方式管理內存?緩存
我該爲個人實例SGA,PGA分別設置多大呢?安全
我該爲buffer cache,shared pool分配多大的內存空間?服務器
什麼狀況下我該使用大頁?爲何大頁這個詞最近幾年這麼容易聽到?微信
有沒有一些簡單粗暴的算法來搞定這一切?session
寫這篇文章的初衷也來源於上面這些很是正常的疑問,若是這篇文章能給有這些疑惑的DBA朋友一些指導和幫助,那肉絲我也就真的功莫大焉了。多線程
2Memory構成架構
在一個運行着Oracle數據庫的專用服務器上,內存基本上被如下內容所佔用:
Kernel Memory
OS Page Table
文件系統Cache
SGA
PGA
Oracle進程
其餘進程(RMAN,非Oracle的進程等等)
嚴格來講OS Page Table也算是Kernel Memory部分的內容,因爲本文後面會重點講大頁的內容,所以把OS Page Table這部分在圖中獨立了出來,以引發讀者注意。必需要強調,Oracle不該該使用掉主機上的全部內存,過量的內存分配會誘發操做系統SWAP的產生,致使Oracle性能嚴重下降,在RAC環境下,內存不足還很是容易致使RAC節點的驅逐。對於Oracle兩大塊內存:SGA和PGA,DBA必定要仔細根據系統特色、業務使用特色作好規劃和設計,以防出現OS內存不夠用的狀況。
3內存自動化發展歷程
咱們首先了解一下Oracle內存發展的歷程,基本上Oracle的內存管理在版本的演進過程當中沿着愈來愈智能化、自動化、傻瓜化的方向前進。接觸過MYSQL等數據庫的DBA朋友應該比較清楚,這些數據庫基本上都還須要DBA去決定每一個內存組件的大小,而Oracle已經從9I版本開始就邁向智能化、自動化的過程了。下圖是Oracle內存管理的一個演進圖:
4PGA 自動管理
Oracle是多進程的架構,這點區別於MYSQL,MYSQL是單進程多線程的架構,Oracle會爲每個用戶鏈接建立一個獨立的操做系統進程來爲用戶提供服務,這個進程叫作服務器進程或者影子進程,它像是用戶的一個代理,來操做數據文件或者SGA內存,因爲服務器進程的代碼是Oracle公司開發的,因此Oracle公司徹底相信這些進程或代碼是安全的,所以這些進程能夠直接操做數據文件和SGA內存,這些進程接受用戶進程發送的指令,並完成相關的操做,並根據須要來給用戶進程返回結果。
因爲服務器進程是操做系統上的一個進程,所以它自己須要佔用一些操做系統內存,除此以外,進程在對數據進行讀取、排序、hash過程當中,也會佔用必定量的內存,在Oracle 9I版本以前,對於服務器進程的內存管理是由一些參數去控制的,如下參數表明每個服務器進程可使用的不一樣區域的內存大小(都是進程的私有內存區域):
SORT_AREA_SIZE
HASH_AREA_SIZE
BITMAP_MERGE_AREA_SIZE
CREATE_BITMAP_AREA_SIZE
例如,SORT_AREA_SIZE控制了每個進程可用的排序區大小,HASH_AREA_SIZE參數控制了每個進程可用的hash區大小,這些參數都有默認值,可是默認值是否合適,須要打上一個大大的問號,由於不一樣的任務對於PGA內存的不一樣區域有不一樣的要求,例如,若是是作排序操做,就對排序區內存要求較大,而對hash區沒任何的要求。固然若是默認值不合適,DBA能夠手工調整這些區域的大小。
Oracle 9I版本出現了PGA的自動管理,再也不須要像9I以前版本須要設置一系列參數來控制PGA的使用,只須要設置PGA_AGGREGATE_TARGET爲一個值,就能夠控制全部的服務器進程的PGA使用量,至於每一個服務器進程使用了多少排序區,hash區,都交給Oracle去控制。
通常狀況下對於PGA的大量使用有以下幾種操做:
hash 對於hash join操做,hash桶所佔用的內存就在進程的私有PGA內存中,而不是在共享內存SGA中,若是使用PGA手工管理的話,能夠經過HASH_AREA_SIZE參數來動態調整會話進行hash操做可以使用的內存量。
sort 對於排序操做,例如查詢語句裏的order by、建立索引的排序操做等佔用的內存也在PGA中,若是使用PGA手工管理,能夠經過SORT_AREA_SIZE參數動態調整會話排序操做可使用的內存量。
parallel 並行操做簡直能夠說是PGA內存的殺手,每個並行進程都能使用到最多2G的PGA內存,固然Oracle會確保全部的並行slave使用的PGA內存不能超過PGA_AGGREGATE_TARGET的一半。
如今Oracle的版本已經出到了12C,PGA的自動管理已經發展了不少個年頭,若是是我的,也應該是一個很是成熟的小夥子了,甚至是位大叔了,絕大部分數據庫操做徹底不必再去手工調整PGA的一些參數。
不過,咱們依然能從互聯網上、論壇上看到有不少DBA對這種手工調整PGA的技術崇拜有加(我之前也是),確實在一些狀況下,經過手工調整PGA的相關內存區,能夠達到加速排序等一些操做的目的,可是若是須要操做的數據量很是的大,那這種調整每每是費時費力,甚至是徒勞的,由於對於一個進程的私有PGA內存來講,像sort,hash等P區域的內存分配是有限制的,如今11GR2的版本對於每一個進程的PGA內存最大限制默認是2個G,且排序區可使用的只有1個G,若是你的排序等操做須要的內存遠遠不止1,2個G,那麼這種優化就很是的徒勞,甚至還可能變慢(肉絲親身遭遇過變慢的案例)。
是否使用PGA自動管理由參數WORKAREA_SIZE_POLICY控制,它的值能夠爲auto和manual,顧名思義,auto爲PGA自動管理,manual爲PGA手工管理,回到9I以前的使用方式。
這裏肉絲提供幾個你們可能會感興趣的隱含參數,好比我上面提到了每一個進程最大能使用的PGA不能超過2個G,經過修改隱含參數能夠突破這個限制。>肉絲在這裏警惕各位,這些參數若是要在生產環境使用,請在你的數據庫版本下作好測試(包括相同的OS及版本)。
如下爲11GR2版本的狀況,其餘版本並未作測試:
_PGA_MAX_SIZE 每一個進程的PGA的最大內存大小。默認值爲:2147483648,2個G,單位爲B。
_SMM_MAX_SIZE 每一個進程的工做區的大小,默認值爲1/2 _PGA_MAX_SIZE,1048576 ,單位KB,1GB,排序區、hash區都屬於工做區的範圍。64位系統下真實使用的排序區內存不能超過4GB。
_SMM_PX_MAX_SIZE 全部並行查詢的SLAVE進程可以用到的PGA總量。默認值爲 1/2 pga_aggregate_target,單位爲KB,RAC環境下,每一個節點均可以用到這麼多內存。
以上所有爲動態參數,能夠在session/system級別來在線修改。
上面的參數調整後,必定要設置對應的pga_aggregate_target,不然以上調整可能會不起做用,建議設置爲修改後的_SMM_PX_MAX_SIZE的值的兩倍。
默認狀況下,每一個進程使用的排序區不能超過1G。由參數_SMM_MAX_SIZE(單位KB)控制,默認爲_PGA_MAX_SIZE(單位B)的一半。例如,並行度20建立索引,總共可使用的排序區大小爲20*1G=20G,可是同時還受參數_SMM_PX_MAX_SIZE的控制,全部的slave佔用的內存不能超過_SMM_PX_MAX_SIZE的值(單位爲KB),默認爲pga_aggregate_target的一半。同時64位系統下,每一個進程可使用的排序空間不能超過4個G。因此即便把_SMM_MAX_SIZE調整大於4個G也沒有用。_SMM_PX_MAX_SIZE,全部並行查詢的SLAVE進程可以用到的PGA總量。每一個RAC 節點均可以用到這麼多,限制的是本節點全部並行slave可以消耗的PGA。
如何爲PGA_AGGREGATE_TARGET設置一個合理的值?
PGA_AGGREGATE_TARGET的設定常常是一個摸索的過程,這裏給出官方的一個分配指導原則
上面公式中的TOTAL_MEM * 80%表明着Oracle可使用的全部內存爲操做系統的80%,再根據不一樣類型業務的特色,OLTP系統,能夠在此基礎上分配20%的內存給PGA,DSS分析型系統,能夠給出剩餘內存的50%。這個只是一個指導的意見,具體狀況要具體分析。例如,你的OLTP系統上有成千上萬個鏈接,那麼你能夠粗略的按照每一個進程佔用10M的內存來大致的計算一下PGA須要佔用的內存空間,再者,假如你的系統不但鏈接數很是多,並且活躍的鏈接數也很是的多,那麼你能夠按照每一個進程至少12M的內存來進行估算,更爲重要的,系統中假如存在很是多的臨時性的計算任務,那麼要爲PGA預留的內存就更多了。 例如,並行度設置爲5建立索引,每一個並行進程佔用的PGA內存接近1個G:
因此你在爲系統規劃PGA內存時不要忘了這些臨時性任務須要佔用的內存。他們多是很大的一塊哦。
該爲數據庫分配多少的PGA內存,除了把鏈接數的多少這個指標做爲一個考量因素外,還須要關注活躍鏈接數的多少,這是由於不少系統鏈接數雖然很是的多,可是去數據庫裏一統計發現,絕大部分的鏈接已經幾個小時甚至幾天都沒活躍過了,這每每是應用程序的鏈接池不加以管理的結果(也多是其餘緣由)。對於不活躍的鏈接,Oracle每一個進程的PGA佔用不會太大,按照10M計算是個合理安全的值。AIX下能夠大一些,按照每一個15M-20M計算。
這裏再提供一種估算每一個空閒的服務器進程佔用OS內存的方法。 首先經過操做系統命令free -m查看一下當前OS剩餘的內存,69590M
再次查看剩餘的操做系統內存,經過沒建立鏈接以前的剩餘內存減去建立完2000個鏈接以後的剩餘內存能夠估算出每一個進程佔用的內存大約爲(59332-44548)/ 2000=7M
讀者須要牢記,減小的7M內存中,絕大部分都是進程自己佔用的,只有1-2M的內存是PGA佔用的。所以上面給你們推薦的值是10-12M,也就是給進程預留出一些PGA的內存來。
確認一個空閒進程佔用的真正PGA內存有多大,能夠經過v$process視圖中PGA_ALLOC_MEM字段來得到,以下:只有1.49M。可是就像上面已經提到的,這個進程從操做系統層面看卻佔用了7M左右的內存。
pga_aggregate_target參數指定的值並非一個硬限制,直到Oracle 12C才提供了一個參數來強制限制PGA的使用量。若是讀者不知道該爲本身系統的PGA設置一個什麼樣的值,能夠經過視圖v$pgastat中的maximumPGAallocated,totalPGAallocated值做爲參考,前者表明自實例啓動以來最大的PGA使用峯值,後者表明當前PGA的使用量,不過這個視圖最大的缺點是不能看到各個時間段的PGA整體使用狀況,這裏肉絲給你們提供一個更好的視圖來做爲參考vsysmetric_history
上面查詢的輸出表明瞭各個時間段的,PGA內存的使用量,結果集並無徹底列出來,讀者能夠根據PGA各個時間段的使用量來更加精準的去爲本身系統的PGA如何作設定作決策。設定PGA的過程是一個按部就班的過程。再次強調,一個進程佔用的內存除了PGA以外,進程自己也會佔用內存,這點上面咱們已經討論過。
按照Oracle 2015年OOW上的一份PPT提到,12C以前版本,PGA最多可用的內存可達到PGA_AGGREGATE_TARGET設定值的三倍,這裏你聽一下就好了,沒必要當真。
若是生產環境真的遭遇了PGA嚴重使用過量的狀況,能夠經過Event 10261 來限制某個/全部進程PGA的使用,level後面值的單位爲KB。
一旦進程超出PGA的設定配額,會被後臺進程殺掉並報錯,不一樣的版本可能報錯的信息不同:
For 11.2.0.4 and 12.1.0.1+, ORA-10260
For 11.1 - 11.2.0.3, ORA-600 [723]
12C PGA_AGGREGATE_LIMIT
12C以前的版本對於PGA的使用限制並無一個硬限制,這個可能會致使一些問題,好比不加以限制後可能會致使OS SWAP的問題,一旦出現SWAP會致使Oracle性能的急劇降低,甚至致使DOWN機,我曾經遭遇過的一個案例是出現SWAP後,LGWR進程自己的內存出現了SWAP,數據庫系統的表現是幾乎徹底HANG死,最後沒辦法只能重啓解決問題。
對於這個新特性的使用是經過參數PGA_AGGREGATE_LIMIT來限制PGA的使用上線,它是一個推導參數,在使用ASMM狀況下,取如下的最大值
2GB
200% PGA_AGGREGATE_TARGET
3MB* PROCESSES
在使用AMM狀況下,肉絲還未找到PGA_AGGREGATE_LIMIT取值的規律,若是你知道,請告訴我哦。
5MSMM
10G前SGA的管理是經過手工設置一系列的參數來實現的,例如重要的參數有如下幾個:
buffer_cache_size
shared_pool_size
large_pool_size
stream_pool_size
log_buffer
SGA是一大塊內存的統稱,由上面列出的組件組成,10G以前的版本,DBA須要對SGA的各個內存區域進行手工設置,這可能對一個DBA無形中要求變得很是的高,須要瞭解業務,瞭解熱點數據量,瞭解SQL的使用方式,是否存在大量不一樣文本的SQL等等來決策來給每一個區域分配多少內存。使用過這個版本的DBA基本都遭遇過一個經典的報錯:ORA-04031,通常是因爲shared pool內存不夠致使,這個不夠的緣由可能有不少,共享池內存的嚴重碎片化,大量的硬解析,巨大的PL/SQL文本等等均可能會致使這個問題。下面咱們來看下,手工管理SGA狀況下,如何考慮爲buffer cache和shared pool這兩個最重要的內存組件分配內存。
Buffer Cache
Buffer Cache俗稱數據塊高速緩存,是用來緩存數據塊的拷貝的,Oracle經過改進後的LRU算法以期待這些數據塊後續被高效的重用。服務器進程從磁盤讀入的數據就放在這塊內存中,修改數據時,也是在這個區域對數據進行修改。並無一個給buffer cache分配內存的黃金法則,仍是要根據操做系統的內存大小,業務的熱點數據量、業務的類型等因素來決定給buffer cache分配多大的內存大小。咱們先看下如何決定整個SGA的大小,對於SGA的分配原則,官方建議以下:
上面的公式格式跟PGA的公式大同小異,刨去20%內存給操做系統以後,分爲了避免同的系統類型,基本上是OLTP系統,大部分的內存給buffer cache,DSS類的系統,buffer cache沒那麼重要,能夠給到50%甚至更低。 至於SGA中多少能夠分配給buffer_cache,要看實際狀況。DBA能夠經過查看buffer cache的命中率來粗略瞭解是否給buffer cache分配了足夠的內存。可是熟悉個人朋友都知道,我是OWI方法論的踐行者,對於命中率的崇拜在Oracle裏已然不該該再存在,可是命中率做爲一種性能診斷的輔助手段依然具備它的價值。若是系統的SQL都足夠優化後,命中率不高,必定程度上意味着可能buffer cache給小了或者你的業務訪問的數據很是的離散,熱點數量太少。
這裏肉絲給出的優化思路是自頂向下,命中率低是一個表象,最上層的應用是否是調用了大量不須要調用的SQL,這些SQL是否是缺乏索引,SQL都足夠優化後,DBA是否是考慮加大buffer cache來提高性能,加大以後仍是不行,是否是要考慮增長系統內存來進一步提升buffer cache的大小,最後是否是須要爲數據庫多加幾個盤或者使用SSD來提升性能。
採用自頂向下的分析方法有利於真正發現問題所在並且以最低的代價解決問題,若是僅僅是一個SQL因爲缺乏索引而致使整個數據庫系統緩慢,DBA直接就去加盤擴容IO,那麼最終會發現花費了這麼大的代價,治標不治本,問題依然沒有解決。上面給出的公式並不適用於全部狀況,特別是OLTP系統,若是進程數很是的多,那麼須要進一步下降SGA佔用內存的比例,以預留出更多內存給PGA使用。
Shared Pool
Oracle佔用量最大的兩塊內存除了buffer cache區就是Shared Pool的內存了,它的結構很是的複雜,並且因爲要緩存SQL代碼這種非標準大小的文本,常常會產生大量的碎片化內存,shared pool整體上包含了兩大部分,一塊是library cache區,用來緩存SQL、PL/SQL代碼,保存它們的執行計劃,提升SQL的解析效率,若是你的應用代碼歷來不使用綁定變量,那麼這一塊的內存對你來講是一個很大的負擔,可是Oracle裏是沒法關閉library cache區的,所以對於OLTP系統,請確保SQL都使用了綁定變量。第二大塊區域是row cache區,用來緩存數據庫的數據字典,因爲保存在裏面的信息是以行的形式存在,所以叫row cache。
對於這一塊的內存,依據數據庫中元信息(metadata)的多少而決定,若是數據庫中有幾十萬的對象,那麼這一塊的內存就會佔用比較大,同時表上的不少列都有直方圖信息,也會致使這一區的內存佔用比較大。在一個穩定的系統中,這一區域的內存基本上是靜態的,Oracle中幾乎沒有操做會頻繁修改row cache區。有個例外狀況是沒有cache屬性的sequence,若是這種sequence調用頻繁,就會觸發頻繁的修改sequence的屬性值,進而可能會產生row cache lock的一些等待,優化的辦法是爲每個sequence設置足夠的cache值。 >若是應用程序沒有使用綁定變量,並且難以修改,能夠經過設置cursor_sharing爲force來嘗試解決問題。
這裏肉絲再講一個親身經歷的案例,老DBA嘛,可能技能已經很少,但故事仍是有的,曾經幫一位客戶解決了一個free buffer waits的案例,這個等待事件的出現通常說明buffer cache太小,或者全表掃描、寫入操做比較多、寫髒數據比較慢,從AWR報告看,free buffer waits排在TOP EVENT的第一名,佔用的DB TIME已達到了百分之七八十,並且從awr報告中發現客戶的shared pool內存佔用已經達到了接近50G,而分析數據庫一個月以前的AWR報告,shared pool的內存只有3個G左右的大小,基本上能夠認定爲shared pool內存佔用過大,而致使buffer cache不夠用,進而出現了free buffer waits等待事件,通過跟客戶溝通後知道,之前一直比較穩定,最近作過的大的變動是給數據庫使用了oracle 的flahcache,經過MOS上搜索flashcache關鍵字最終發現,在11.2.0.4,Oracle RAC若是使用了flash cache,那麼會在shared pool 中分配額外的內存存放GCS資源。多出的內存爲:208 bytes * the total number of (flash) buffer blocks。由於這裏提醒廣大DBA朋友,若是你打算使用Oracle的FlashCache那麼請爲它預留出足夠的shared pool內存。
7ASMM
10G 版本Oracle推出了ASMM,自動SGA管理,它的出現必定程度上幫助DBA解決了管理SGA的問題,經過設置參數sga_target爲非0值來啓用ASMM。可是在10GR1,包括10GR2的早期版本,ASMM還不夠成熟存在比較多的BUG,致使了比較多的問題,因此當時DBA在一些核心的生產環境,仍是沿用了9I時候的手工SGA管理。自動SGA管理,再也不須要爲每一個內存組件設定值,固然若是你設置sga_target的同時,設置了db_cache_size這些參數,那麼db_cache_size這些參數值會做爲最小值要求。
若是sga_target設置爲0,memory_target也爲0,則迴歸到傳統的MSMM管理。經過使用ASMM能夠很大程度上解決上面提到的ORA-04031的錯誤。在使用了ASMM後,去查看spfile文件,會發現多了一些雙下劃線打頭的內存參數如__db_cache_size,這些內存參數是Oracle實例運行過程當中動態產生固化到spfile中的,若是實例運行的時間足夠長,這些參數的值被固話後,至關於有了一個基於自身環境的最佳實踐參數,數據庫實例重啓後,會沿用固化在spfile中的這些參數值。 > 11G版本即便sga_target設置爲0,memory_target也設置爲0,也可能會發現SGA的pool之間Granule的移動,這是11G的新Linux特性,經過參數_memory_imm_mode_without_autosga來控制。 >
Granule
ASMM技術的實現,內部是經過Granule在內存組件之間移動來實現。這裏對Granule作一點解釋,Oracle 10G引入的自動共享內存管理,目的是爲了解決下面的問題,「我應該把db_cache_size設置爲多大?我應該把shared_pool_size設置多大?那麼10G之後,Oracle給出的答案是,「你不用再考慮這個問題了,我經過算法幫你搞定「。
簡單來講,就是經過比較經過增長數據塊緩存減小的磁盤IO時間與經過增長共享池優化而節省的時間,經過比對,來得出是否須要在二者間來移動內存。爲了讓內存在db_cache_size和shared_pool_size之間高效移動,Oracle在9I版本中從新構建了SGA,也就是使用固定大小的內存塊-Granule,Granule會隨着操做系統、Oracle版本以及SGA大小的不一樣而不一樣,讀者能夠經過以下的SQL語句來查看當前實例的Granule的大小:
in Oracle Database 11.2.0.2 indicates that the granule size increases from 64MB to 128MB when the SGA_TARGET parameter is set to 1 byte greater than 32G, and jumps to 256MB when the SGA_TARGET parameter is set to 1 byte greater than 64G. A granule size of 32MB is possible when the SGA_TARGET was set to a value between 8G + 1 byte to 16G.
8AMM
有了PGA的自動管理,SGA的自動管理,Oracle 這個強迫症患者終於在11G這個版本推出了AMM,自動內存管理,因爲使用了AMM後就不能使用大頁,所以這個功能其實一直沒被普遍使用,經過這個功能DBA只須要設置memory_target一個參數就能夠完成整個數據庫實例內存的配置,就像ASMM致使了一些雙下劃線隱含參數的產生,AMM一樣致使了一些雙下劃線隱含參數的產生,例如:__pga_aggregate_target,__sga_target。
並且在11.2.0.2版本以前,DBCA建庫默認就是AMM管理(有些時候Oracle膽子真的是很大),11.2.0.3之後開始DBCA建庫時會檢測操做系統內存大小,大於4G內存默認爲ASMM,小於4G內存默認爲AMM。一樣若是你設置AMM後,也設置了SGA_TARGET等參數,那麼這些參數會做爲最小值要求。
AMM最大的問題是不能使用大頁內存。關於使用大頁的重要性會在本文後面部分詳細介紹。 >Doc 749851.1 > > Doc 1453227.1.
11G後因爲出現了AMM,若是你作DBA時間足夠長,你必定遇到過下面這個錯誤
這個錯誤給人莫名其妙的感受,「MEMORY_TARGET特性不被支持」,其實不是特性不被支持,這是因爲AMM使用的是操做系統的共享內存文件系統,位於/dev/shm下,若是配置的內存文件系統比較小,小於了memory_target的值就會報錯,通常在Linux主流的操做系統上,這個內存共享文件系統的值是內存大小的一半,若是讀者遭遇了這個問題,要不去調小memory_target的參數值,要不經過以下辦法去修改這個共享內存文件系統的大小:
這裏指出一點,11G ASM默認會使用AMM,官方強烈建議不要修改這個默認行爲。ASM裏要求MEMORY_TARGET的最小值爲256M。若是設置了低於256M的值,Oracle會自動增長內存到256M。 對於ASM的發佈版:11.2.0.3/11.2.0.4/12.1,Oracle強烈建議把memory_target設置爲1536M,這個值被證實在絕大部分的環境裏都是足夠的。
使用了ASM後,數據庫實例的shared_pool內存須要從新評估計算,以下公式是在正常shared pool的基礎上須要額外增長的大小:
若是ASM磁盤組是external redundancy,須要在2MB基礎上,每100G的空間,增長1MB。
若是ASM磁盤組是normal redundancy,須要在4MB基礎上,每50G的空間,增長1MB。
若是ASM磁盤組是high redundancy,須要在6MB基礎上,每33G的空間,增長1MB。
ASM & Shared Pool (ORA-4031) (文檔 ID 437924.1)
9大頁
對於類Linux系統,CPU必須把虛擬地址轉換程物理內存地址才能真正訪問內存。爲了提升這個轉換效率,CPU會緩存最近的虛擬內存地址和物理內存地址的映射關係,並保存在一個由CPU維護的映射表中,爲了儘可能提升內存的訪問速度,須要在映射表中保存儘可能多的映射關係。這個映射表在Linux中每一個進程都要持有一份,若是映射表太大,就會大大下降CPU的TLB命中率,主流的Linux操做系統,默認頁的大小是4K,對於大內存來講,這會產生很是多的page table entries,上面已經提到,Linux下頁表不是共享的,每一個進程都有本身的頁表,如今隨便一個主機的內存都配置的是幾十個G,幾百個G,甚至上T,若是在上面跑Oracle不使用大頁,基本上是找死,由於Oracle是多進程架構的,每個鏈接都是一個獨佔的進程,大內存+多進程+不使用大頁=災難,肉絲在8年的DBA生涯裏,至少幫助不下5個客戶處理過因爲沒有使用大頁而致使的系統故障,而這5個客戶都是近三四年遇到的,爲何大頁這個詞提早個三五年並無被頻繁提起,而當下,大頁這個詞在各類技術大會,最佳實踐中成爲熱門詞彙?
這是由於最近幾年是Linux系統被大量普及應用的幾年,也是大內存遍地開花的幾年,並且如今一個數據庫系統動不動就是幾百上千個鏈接,這些都促成了大頁被愈來愈多的被關注到。
大頁的好處
咱們來看一下使用了大頁的好處:
少的page table entries,減小頁表內存
pin住SGA,沒有page out
提升TLB命中率,減小內核cpu消耗
在沒有使用大頁的系統上,常常可能會發現幾十上百G的頁表,嚴重狀況下,系統CPU的sys部分的消耗很是大,這些都是沒使用大頁的狀況下的一些症狀。
大頁的特色/缺點
要預先分配
不夠靈活,甚至須要重啓主機
若是分配過多,會形成浪費,不能被其餘程序使用。
大頁的分配方法
經過在文件/etc/sysctl.cnf中增長vm.nr_hugepages參數來爲大頁設定一個合理的值,值的單位爲2MB。或者經過echo 一個值到/proc/sys/vm/nr_hugepages中也能夠臨時性的對大頁進行設定。 至於應該爲大頁設定多大的值,這個要根據系統SGA的配置來定,通常建議大頁的總佔用量大於系統上全部SGA總和+2GB。
HugePages on Oracle Linux 64-bit (文檔 ID 361468.1),AIX頁表共享,通常不用設置大頁。
大頁的原理
如下的內容是基於32位的系統,4K的內存頁大小作出的計算: 1)目錄表,用來存放頁表的位置,共包含1024個目錄entry,每一個目錄entry指向一個頁表位置,每一個目錄entry,4b大小,目錄表共4b*1024=4K大小 2)頁表,用來存放物理地址頁的起始地址,每一個頁表entry也是4b大小,每一個頁表共1024個頁表entry,所以一個頁表的大小也是4K,共1024個頁表,所以頁表的最大大小是1024*4K=4M大小 3)每一個頁表entry指向的是4K的物理內存頁,所以頁表一共能夠指向的物理內存大小爲:1024(頁表數)*1024(每一個頁表的entry數)*4K(一個頁表entry表明的頁大小)=4G 4)操做系統將虛擬地址映射爲物理地址時,將虛擬地址的31-22這10位用於從目錄表中索引到1024個頁表中的一個,將虛擬地址的12-21這10位用於從頁表中索引到1024個頁表entry中的一個。從這個頁表entry中得到物理內存頁的起始地址,而後將虛擬地址的0-12位用做4KB內存頁中的偏移量,那麼物理內存頁起始地址加上偏移量就是進出所須要訪問的物理內存地址。
因爲32位操做系統不會出現4M的頁表,由於一個進程不能使用到4GB的內存空間,有些空間被保留使用,好比用來作操做系統內核的內存。並且頁表entry的建立出如今進程訪問到一塊內存的時候,而不是一開始就建立。
頁表內存計算
在32位系統下,一個進程訪問1GB的內存,會產生1M的頁表,若是是在64位系統,將會增大到2M。 很容易推算,若是一個SGA設置爲60G,有1500個Oracle用戶進程,64位Linux的系統上,最大的頁表佔用內存爲:60*2*1500/1024=175G,是的,你沒看錯,是175G!可是實際狀況看到的頁表佔用可能沒有這麼大,打個百分之四五十的折扣,這是由於只有服務器進程訪問到SGA的特定區域後,進程才須要把這一塊對應的頁表項加入到本身的頁表中。
11.2.0.3版本
11.2.0.3版本以前,若是分配的大頁數量不足,那麼Oracle啓動過程當中不會使用大頁,轉而使用小頁,可是在11.2.0.3版本後,Oracle在啓動時一樣會嘗試使用大頁,若是大頁的數量不夠,那麼會把當前配置的大頁使用完,不夠的部分再從小頁中去獲取,這一行爲其實是經過Oracle的一個參數來控制USE_LARGE_PAGES,後面會對這個參數作詳細解釋。經過數據庫實例的alert文件能夠清楚的看到這一狀況的發生:
Total Shared Global Region in Large Pages = 1024 MB (85%),表明只有85%的SGA被放在了大頁中。RECOMMENDATION部分,建議你至少增長89個大頁來讓SGA徹底放到大頁中。
USE_LARGE_PAGES
這個參數用來控制數據庫實例啓動時,對於大頁內存的使用行爲。有3個值在11.2.0.3版本以前,11.2.0.3版本多了一個值auto:
true 默認值,儘量使用大頁,有可能有一些頁在大頁中,有一些在小頁中,這種狀況下經過操做系統命令ipcs -ma可能會看到內存分段(內存分段可能有多重狀況都會致使,例如開啓numa也可能會致使內存分段)
false 不使用大頁
only 選項表明強制使用大頁,不然沒法啓動
auto (11.2.0.3)在實例啓動時,經過後臺進程dism echo xxx > /proc/sys/vm/nr_hugepages 來儘量的使用大頁
如下代碼爲在參數設置爲auto狀況下alert的輸出:
能夠看到啓動實例過程當中,優先啓動了DISM進程,經過這個進程來自動完成大頁的配置。$Oracle_HOME/bin/oradism的權限也是root權限,由於若是是grid權限不能完成大頁的配置echo xxx > /proc/sys/vm/nr_hugepages。
Transparent Hugepage
從RedHat6, RedHat7, OL6, OL7 SLES11 和 UEK2 kernels開始transparent hugepage被默認開啓,它容許大頁作動態的分配,而不是系統啓動後就分配好,根據Oracle MOS DOC:1557478.1,transparent hugepage致使了不少的問題,建議將其關閉 查看是否啓用了transparent hugepage cat /sys/kernel/mm/transparent_hugepage/enabled [always] never []內的值是當前啓用的值,上面的輸出說明啓用了transparent hugepage。 能夠經過 /etc/grub.conf 文件來關閉transparent hugepage。
經過增長關鍵字transparent_hugepage=never來說transparent hugepage關閉。 也能夠經過開機啓動後,echo相應的值到對應的文件來動態關閉transparent hugepage。
OS層面查看大頁使用狀況
cat /proc/meminfo
HugePages_Total: 43000
HugePages_Free: 29493
HugePages_Rsvd: 23550
Hugepagesize: 2048 kB
HugePages_Total爲所分配的頁面數目,和Hugepagesize相乘後獲得所分配的內存大小。43000*2/1024大約爲84GB。
HugePages_Free爲歷來沒有被使用過的Hugepages數目。即便Oracle sga已經分配了這部份內存,可是若是沒有實際寫入,那麼看到的仍是Free的。這是很容易誤解的地方。
HugePages_Rsvd爲已經被分配預留可是尚未使用的page數目。在Oracle剛剛啓動時,大部份內存應該都是Reserved而且Free的,隨着Oracle SGA的使用,Reserved和Free都會不斷的下降。
HugePages_Free – HugePages_Rsvd 這部分是沒有被使用到的內存,若是沒有其餘的Oracle instance,這部份內存也許永遠都不會被使用到,也就是被浪費了。在該系統上有11.5GB的內存被浪費了。
10最佳實踐
對於Oracle來講,這是一個最佳實踐氾濫的時代,全部的最佳實踐其實都有特定的應用場景,而不是放之四海皆準,可是當今信息爆炸時代(數據庫種類爆炸時代),不少DBA沒有那麼多的耐心去專一學習一門數據庫,只是拿來主義從網上找出一些最佳實踐來,無論三七二十一就用到本身的環境中(甚至是生產環境中),必定程度上來講,崇拜最佳實踐是懶惰的結果。
針對於Oracle的內存分配方式,肉絲給你們推薦在覈心繫統上:
1.使用手工的SGA管理,這種管理方式已經很是的成熟,可是這種方式對DBA要求較高,必定程度上須要瞭解業務特色。
2.若是第一種方法你感受到比較難,那麼使用ASMM,可是爲buffer cache,shared pool設定最小值的方式,這種方式是我很是推薦的方式。
至於AMM這種內存分配方式,因爲不能使用大頁,建議不要去用。
具體到內存如何分配,針對是OLTP場景,仍是OLAP場景,有着不一樣的內存分配原則,即便是OLTP場景,針對進程數的多少,併發數的多少,SQL語句的特色,都會致使產生不一樣的內存分配方法。做爲DBA要掌握基本的Oracle內存使用原理,而後根據實際狀況去根據業務自身特色分配內存。
無論是OLTP系統或者OLAP系統,通常都建議至少爲操做系統預留出20%的內存空間,這些內存空間用於kernal、page table以及一些其餘的進程須要,例如rman備份,文件系統緩存。這個也是Oracle官方的建議。
把這一部分的內存刨去後,針對OLTP系統,能夠考慮先嚐試預留出20%的內存給PGA使用,80%的內存給SGA使用。若是系統上進程數比較多,特別是同時活躍的進程數比較多,須要給PGA預留出更多的內存,能夠按照每一個進程12M的PGA佔用進行計算。
針對OLAP系統,刨去操做系統的預留內存後,能夠考慮預留出50%的內存給PGA使用,50%的內存給SGA使用。畢竟在純OLAP下,buffer cache其實不須要那麼大的內存空間。
SGA、PGA分配好後,要考慮到是否須要爲buffer cache、shared pool來手工設定一個值,就像上文已經提到過的,能夠參考buffer cache 的命中率,Library Hit的命中率做爲一個輔助參考.若是命中率較低,有多是內存分配的不夠合理。
固然你還須要藉助於像AWR報告這樣的工具,根據SQL的執行計劃等內容來進一步的作診斷,好比命中率低的緣由可能不是分配的buffer cache小,而是存在大量的低效的全表掃描,進而致使命中率低,這樣的話,須要優化的就是SQL,而不是繼續加大buffer cache。再好比,若是你發現Library cache Hit比較低,可能並非shared pool比較小,還多是系統的SQL存在大量未使用綁定變量的狀況,致使硬解析太重。
優化常常是個系統工程,不能一蹴而就,特別像Oracle是一個很龐大的複雜系統,對於問題的出現,更是要仔細推敲,不能輕易的下結論。隨着作DBA時間愈來愈長,你也會愈來愈懂TOM的一句話:It depends。
About Me
....................................................................................................................................................
本文來自於微信公衆號轉載文章,如有侵權,請聯繫小麥苗及時刪除
ITPUB BLOG:http://blog.itpub.net/26736162
QQ:642808185 若加QQ請註明您所正在讀的文章標題
【版權全部,文章容許轉載,但須以連接方式註明源地址,不然追究法律責任】
....................................................................................................................................................