LINUX HUGEPAGES在大記憶體資料庫中的應用

yingyifeng306發表於2015-03-05


背景介紹
隨著X86伺服器被越來越多的客戶所接受,LINUX作業系統也越來越多的被作為主流的資料庫伺服器作業系統,我們都知道在現今的IT行業中,記憶體已經相對越來越廉價,一般的普通的X86伺服器記憶體動輒百G甚至T級別,隨著硬體的不斷升級,相應的,軟體的配置也要發生相對變化,從最簡單的理解,作業系統從原先的管理百G以下的記憶體,到現在的管理T級別的記憶體,如果沒有相應的管理方法,相應的管理效率肯定會降低。 

LINUX作業系統程式是透過虛擬地址對記憶體進行訪問,而CPU必須把它轉換成實際的實體記憶體地址才能真正訪問記憶體。而CPU透過快取最近的虛擬記憶體地址和實體記憶體地址的對映關係來提高訪問效率,並且儲存在一個由CPU維護的對映表中。為了儘量提高記憶體的訪問速度,需要在對映表中儲存儘量多的對映關係。我們都知道,在傳統的LINUX記憶體管理模式中,記憶體都是以頁的形式進行分配的,預設每個記憶體頁大小為4K。這就產生了一個問題,在原先的百G左右的記憶體下,可能整個對映表還在可控範圍內,而當記憶體增加到T級別後,記憶體頁依舊是4K大小,這就會導致整個對映表變得非常龐大,導致CPU的檢索效率大大降低。而HUGEPAGES就是在這樣一個環境下產生。

概念普及

hugepage是在Linux2.6核心中被引入的,提供4kpagesize和比較大的pagesize的選擇。huge page 的大小取決於所使用的作業系統的核心版本以及不同的硬體平臺
可以使用$grep Hugepagesize /proc/meminfo來檢視huge page 的大小,對於較大的系統記憶體以及sga,使用hugepage可以極大程度的提高Oracle資料庫效能

注意點:

Hugepage雖然是一個比較好的選擇方案,但仍然需要注意以下幾點:

1. HugePages 在作業系統啟動後,如果沒有管理員的介入,是不會釋放和改變的,是屬於一種常駐記憶體

2. HugePages 也不會被交換.也就是沒有換入換出過程(page-in/page-out)。HugePages一直被pin在記憶體中,這就要求我們不能把HugePages設定過大。

3. 由於AMM(Automatic Memory Management)特性與Hugepages不相容,如果希望使用HugePages需要禁用AMM特性。、

4. Hugepages是在分配後就會預留出來的,其大小一定要比伺服器上所有例項的SGA總和要大,如果比SGA小,oracle SGA將無法使用Hugepages,例如當我們設定SGA40G而設定Hugepages30G那麼oracle將無法使用這30G的記憶體,所以這也是相對比較危險的一點,可能在前期配置中沒有問題,但是後期人為的調整了SGA大小,將SGA的大小超過了Hugepages的大小,那麼就會導致致命的錯誤,最糟糕的結果就是由於oracle無法得到記憶體而宕掉。

操作過程

以下講解如何配置Hugepages過程以RHEL6.2環境為模板,配置過程也可以參見MOS文件:HugePages on Oracle Linux 64-bit (文件 ID 361468.1)

[root@rehl6 ~]# more /etc/redhat-release

Red Hat Enterprise Linux Server release 6.2 (Santiago)

[root@rehl6 ~]# uname -a

Linux rehl6 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011 x86_64 x86_64 x86_64 GNU/Linux


Step 1:檢視當前系統是否配值HugePages

下面的查詢中HugePages相關的幾個值都為0,表明當前未配值HugePages

[root@rehl6 ~]# grep Huge /proc/meminfo

AnonHugePages:   1142784 kB

HugePages_Total:       0

HugePages_Free:        0

HugePages_Rsvd:        0

HugePages_Surp:        0

Hugepagesize:       2048 kB

我們來詳細解釋一下一上4個引數值的意思:

HugePages_Total為所分配的頁面總數目,該值和Hugepagesize相乘後得到所分配的記憶體大小。

HugePages_Free為從來沒有被使用過的Hugepages數目。即使oraclesga已經分配了這部分記憶體,但是如果沒有實際寫入,那麼看到的還是Free的。這是很容易誤解的地方

HugePages_Rsvd為已經被分配預留但是還沒有使用的page數目。在Oracle剛剛啟動時,大部分記憶體應該都是Reserved並且Free的,隨著oracleSGA的使用,Reserved和Free都會不斷的降低

HugePages_Free減去HugePages_Rsvd 這部分是沒有被使用到的記憶體,如果沒有其他的oracleinstance,這部分記憶體也許永遠都不會被使用到,也就是被浪費了。

Step 2:修改使用者的memlock限制

透過修改/etc/security/limits.conf 配值檔案來實現

  該引數的值通常配值位略小於當前的已安裝系統記憶體,如當前你的系統記憶體為30G,可以做如下設定

  *   soft   memlock    30000000

  *   hard   memlock    30000000

  上述的設定單位為kb,不會降低系統效能。至少也要配值為略大於系統上所有SGA的總和。

  退出重新登入並使用ulimit -l 來校驗該設定

 

Step 3:禁用AMM(Oracle 11g)

如果當前的Oracle 版本為10g,可以跳過此步驟。

如果當前的Oracle 版本為11g,由於AMM(Automatic Memory Management)特性與Hugepages不相容,需要禁用AMM。

ALTER SYSTEM RESET memory_target SCOPE=SPFILE;

ALTER SYSTEM RESET memory_max_target SCOPE=SPFILE;

ALTER SYSTEM SET sga_target=g SCOPE=SPFILE;

ALTER SYSTEM SET pga_aggregate_target=g SCOPE=SPFILE;

SHUTDOWN IMMEDIATE;

STARTUP;

實踐證明,在MOS文件中提供的以上方法是不行的,對於重新設定memory_target需要透過匯出引數檔案刪除memory_target及memory_max_target並設定相關的SGA值重新建立spfile才可以。

Step 4:計算vm.nr_hugepages 值

簡單的計算方法如下:(只做系統估計)

簡單的計算原理是total SGA_MAX_SIZE(多個instance的總和)/hugepagesize + N

N為少量記憶體盈餘,一般多出100就足夠了。如果主機記憶體128GB,計劃70GB用於SGA共享記憶體,則大記憶體頁需70×1024/2=35840

使用Oracle 提供的指令碼hugepages_settings.sh的指令碼來計算vm.nr_hugepages的值(這個值設定的是hugepage momory 的大小)

  在執行指令碼之前確保所有的Oracle 例項已啟動以及ASM也啟動(存在的情形下)

  $ ./hugepages_settings.sh

該文件指令碼可以參看MOS文件(Shell Script to Calculate Values Recommended Linux HugePages / HugeTLB Configuration (文件 ID 401749.1)),附錄一提供摘錄

 

Step 5:設定vm.nr_hugepages引數

編輯/etc/sysctl.conf 來設定vm.nr_hugepages引數

  $ sysctl -w vm.nr_hugepages = 1496(該值為上述指令碼獲得的值,vm.nr_hugepages指明瞭記憶體頁數) 

  $ sysctl -p

 

Step 6 重啟主機驗證

HugePages相關引數的值會隨著當前伺服器上的例項的停止與啟動而動態發生變化

  通常情況下,HugePages_Free的值應當小於HugePages_Total的值,在HugePages被使用時HugePages_Rsvd值應當為非零值。

  $ grep Huge /proc/meminfo

  HugePages_Total:   131

  HugePages_Free:     20

  HugePages_Rsvd:     20

  Hugepagesize:     2048 kB

 

  如下面的情形,當伺服器上僅有的一個例項被關閉後,HugePages_Rsvd的值為零。且HugePages_Free等於HugePages_Total

  $ grep Huge /proc/meminfo

  HugePages_Total:   131

  HugePages_Free:    131

  HugePages_Rsvd:      0

  Hugepagesize:     2048 kB  

 

附錄一:

hugepages_settings.sh

#!/bin/bash

#

# hugepages_settings.sh

#

# Linux bash script to compute values for the

# recommended HugePages/HugeTLB configuration

#

# Note: This script does calculation for all shared memory

# segments available when the script is run, no matter it

# is an Oracle RDBMS shared memory segment or not.

#

# This script is provided by Doc ID 401749.1 from My Oracle Support

#

 

# Welcome text

echo "

This script is provided by Doc ID 401749.1 from My Oracle Support

() where it is intended to compute values for

the recommended HugePages/HugeTLB configuration for the current shared

memory segments. Before proceeding with the execution please note following:

 * For ASM instance, it needs to configure ASMM instead of AMM.

 * The 'pga_aggregate_target' is outside the SGA and

   you should accommodate this while calculating SGA size.

 * In case you changes the DB SGA size,

   as the new SGA will not fit in the previous HugePages configuration,

   it had better disable the whole HugePages,

   start the DB with new SGA size and run the script again.

And make sure that:

 * Oracle Database instance(s) are up and running

 * Oracle Database 11g Automatic Memory Management (AMM) is not setup

   (See Doc ID 749851.1)

 * The shared memory segments can be listed by command:

     # ipcs -m

 

 

Press Enter to proceed..."

 

read

 

# Check for the kernel version

KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`

 

# Find out the HugePage size

HPG_SZ=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`

if [ -z "$HPG_SZ" ];then

    echo "The hugepages may not be supported in the system where the script is being executed."

    exit 1

fi

 

# Initialize the counter

NUM_PG=0

 

# Cumulative number of pages required to handle the running shared memory segments

for SEG_BYTES in `ipcs -m | cut -c44-300 | awk '{print $1}' | grep "[0-9][0-9]*"`

do

    MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q`

    if [ $MIN_PG -gt 0 ]; then

        NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q`

    fi

done

 

RES_BYTES=`echo "$NUM_PG * $HPG_SZ * 1024" | bc -q`

 

# An SGA less than 100MB does not make sense

# Bail out if that is the case

if [ $RES_BYTES -lt 100000000 ]; then

    echo "***********"

    echo "** ERROR **"

    echo "***********"

    echo "Sorry! There are not enough total of shared memory segments allocated for

HugePages configuration. HugePages can only be used for shared memory segments

that you can list by command:

 

    # ipcs -m

 

of a size that can match an Oracle Database SGA. Please make sure that:

 * Oracle Database instance is up and running

 * Oracle Database 11g Automatic Memory Management (AMM) is not configured"

    exit 1

fi

 

# Finish with results

case $KERN in

    '2.4') HUGETLB_POOL=`echo "$NUM_PG*$HPG_SZ/1024" | bc -q`;

           echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;

    '2.6') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;

     *) echo "Unrecognized kernel version $KERN. Exiting." ;;

esac

 

# End

 ---------------------------------------------------------------------------------------------------

原部落格地址:http://blog.itpub.net/23732248/
原作者:應以峰 (frank-ying)
----------------------------------------------------------------------------------------------------

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

相關文章