Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 27.1Mb
PDF (A4) - 27.2Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


MySQL 5.6 リファレンスマニュアル  /  ...  /  ラージページのサポートの有効化

8.11.4.2 ラージページのサポートの有効化

ハードウェアまたはオペレーティングシステムのアーキテクチャーによっては、デフォルト (通常は 4K バイト) よりも大きいメモリーページをサポートしています。このサポートの実際の実装は、ベースとなるハードウェアやオペレーティングシステムに依存します。大量のメモリーアクセスがあるアプリケーションの場合、大きいページを使用して、トランスレーションルックアサイドバッファー (TLB; Translation Lookaside Buffer) のミスが減ることによってパフォーマンスが改善される可能性があります。

MySQL では、InnoDB でラージページを使用して、バッファープールと追加のメモリープールにメモリーを割り当てることができます。

MySQL での標準的な大規模ページの使用では、サポートされる最大サイズである 4M バイトまでの使用が試行されます。Solaris では超大規模ページ機能により 256M バイトまでのページの使用が可能です。この機能は最新の SPARC プラットフォームで使用できます。これは --super-large-pages または --skip-super-large-pages オプションを使用して有効または無効にできます。

MySQL は、ラージページのサポートの Linux 実装 (Linux では HugeTLB と呼ばれる) もサポートします。

Linux でラージページを使用する前に、カーネルで、それらをサポートできるようにする必要があり、HugeTLB メモリープールを構成する必要があります。参考のため、HugeTBL API は、Linux ソースの Documentation/vm/hugetlbpage.txt ファイルで説明されています。

Red Hat Enterprise Linux などの一部の最近のシステムのカーネルでは、ラージページ機能がデフォルトで有効にされているようです。使用しているカーネルにこれが当てはまるかどうかを確認するには、次のコマンドを使用し、huge を含む出力行を探します。

shell> cat /proc/meminfo | grep -i huge
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       4096 kB

空でないコマンド出力は、ラージページのサポートが存在することを示しますが、ゼロの値は、使用するように構成されたページがないことを示します。

ラージページをサポートするようにカーネルを再構成する必要がある場合、手順については hugetlbpage.txt ファイルを参照してください。

Linux カーネルでラージページのサポートが有効にされていると仮定し、それを次のコマンドを使用して、MySQL で使用するように構成します。通常、システムが起動するたびにコマンドが実行されるように、システムのブートシーケンス中に実行される rc ファイルまたは同等の起動ファイルにこれらを入れます。コマンドは、ブートシーケンスの早期の、MySQL サーバーが起動する前に実行されるべきです。システムに適切なように、割り当ての数値とグループ番号を変更してください。

# Set the number of pages to be used.
# Each page is normally 2MB, so a value of 20 = 40MB.
# This command actually allocates memory, so this much
# memory must be available.
echo 20 > /proc/sys/vm/nr_hugepages

# Set the group number that is permitted to access this
# memory (102 in this case). The mysql user must be a
# member of this group.
echo 102 > /proc/sys/vm/hugetlb_shm_group

# Increase the amount of shmem permitted per segment
# (12G in this case).
echo 1560281088 > /proc/sys/kernel/shmmax

# Increase total amount of shared memory.  The value
# is the number of pages. At 4KB/page, 4194304 = 16GB.
echo 4194304 > /proc/sys/kernel/shmall

MySQL で使用する場合、通常 shmmax の値を shmall の値に近くなるようにしたいと考えます。

ラージページの構成を確認するには、前述のとおりに再度 /proc/meminfo をチェックします。これで、0 以外の値が表示されるはずです。

shell> cat /proc/meminfo | grep -i huge
HugePages_Total:      20
HugePages_Free:       20
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       4096 kB

hugetlb_shm_group を使用するための最後の手順は、mysql ユーザーに、memlock 制限として unlimited 値を指定することです。これを実行するには、/etc/security/limits.conf を編集するか、mysqld_safe スクリプトに次のコマンドを追加します。

ulimit -l unlimited

ulimit コマンドを mysqld_safe に追加すると、mysql ユーザーに切り替える前に root ユーザーの memlock 制限が unlimited に設定されます。(これは、mysqld_saferoot によって起動されたものと仮定します。)

MySQL のラージページのサポートはデフォルトで無効にされています。それを有効にするには、サーバーを --large-pages オプションで起動します。たとえば、サーバーの my.cnf ファイルで次の行を使用できます。

[mysqld]
large-pages

このオプションを使用すると、InnoDB はそのバッファープールと追加のメモリープールに自動的にラージページを使用します。InnoDB がこれを実行できない場合、従来のメモリーの使用に戻り、エラーログに警告を書き込みます: Warning: Using conventional memory pool

ラージページが使用されていることを確認するには、再度 /proc/meminfo をチェックします。

shell> cat /proc/meminfo | grep -i huge
HugePages_Total:      20
HugePages_Free:       20
HugePages_Rsvd:        2
HugePages_Surp:        0
Hugepagesize:       4096 kB

User Comments
  Posted by John Engelke on February 21, 2010
An error will always generate on initial startup of mysqld since the 'mysql_install_db' script is run necessarily prior to 'mysqld_safe' in the daemon startup script. In order to allow the initialization of the database using huge page support, ease the memlock limit by typing 'ulimit -l unlimited' as root at the command prompt before either starting mysqld or executing mysql_install_db. This is in addition to adding it to the mysqld_safe script.

Also, choose values wisely since I believe that the 'nr_hugepages' parameter will actually reserve physical memory. At 2MB per page that means a value of 512 will reserve 1GB.

If you are getting the error 22 or 12 at initialization, both of the above tips should help immensely. (See also http://time.to.pullthepl.ug/story/2008/11/18/9/-MySQL-Large-Pages-errors .)
  Posted by John Mancuso on November 8, 2010
I had an issue where large pages were enabled however mysql was not using the whole chunk of large page memory allocated (approx 23 GB) so the server was swapping constantly. This was MySQL 5.1.49 using the new innodb plugin 1.0.10 (also applies to MySQL 5.5 and above most likely). The solution: the amount of large page memory you allocate should be > innodb_buffer_pool size.

I allocated 13,500 large pages for a 24 GB buffer pool and it works fine now.
  Posted by Rainer Stumbaum on August 23, 2011
Hi,

following system:
Debian 6 4CPU 20Gbyte RAM dedicated MySQL server

my.cnf:
...
innodb_buffer_pool_size = 12000M
innodb_additional_mem_pool_size = 16M
...

Therefore the following /etc/sysctl.d/mysql.conf
----
# Set the number of pages to be used:
# Add innodb_buffer_pool_size and
# innodb_additional_mem_pool_size
# and divide by Hugepagesize.
# Each page is normally 2MB, so a value of 6100 = 12200MB.
# This command actually allocates memory, so this much
# memory must be available.
# Important:
# ulimit -l unlimited
# and set in my.cnf:
# ...
# [mysqld]
# large-pages
# ...
vm.nr_hugepages = 6100

# Set the group number that is permitted to access this
# memory (110 in this case). The mysql user must be a
# member of this group.
vm.hugetlb_shm_group = 110

# Set the amount of shmem permitted per segment in bytes
# (12199Mb in this case).
kernel.shmmax = 12791578624

# Set the total amount of shared memory. The value
# is the size in pages. At 4KB/page, 3122944 = 12199MB.
kernel.shmall = 3122944
----

I added the ulimit to the startup script and added the large-pages in the mysqld section.

But I get the following error:
....
110823 13:41:00 mysqld_safe Starting mysqld daemon with databases from /mnt/mysql/data
110823 13:41:00 [Warning] '--log_slow_queries' is deprecated and will be removed in a future release. Please use ''--slow_query_log'/'--slow_query_log_file'' instead.
110823 13:41:00 [Note] Plugin 'FEDERATED' is disabled.
InnoDB: HugeTLB: Warning: Failed to allocate 12582928384 bytes. errno 28
InnoDB HugeTLB: Warning: Using conventional memory pool
...

The existing samples are not very clear - I would like to know if my example is right and clear enough for calculation the size correctly.
  Posted by Rainer Stumbaum on August 23, 2011
Got it to work:
Instead of using the calculated 12200MB I used 15GB.
root@mysql04.dc1:~# ipcs

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x6c1009eb 0 zabbix 600 693504 8
0x00000000 32769 mysql 600 1279262720 1 dest
0x00000000 65538 mysql 600 12585009152 1 dest

root@mysql04.dc1:~# grep -i huge /proc/meminfo
HugePages_Total: 7680
HugePages_Free: 7394
HugePages_Rsvd: 6325
HugePages_Surp: 0
Hugepagesize: 2048 kB
root@mysql04.dc1:~#

So the calculation seeems somehow to be wrong...

  Posted by DANGLADE JEAN-SEBASTIEN on November 13, 2012
I hope this comment will save severals hours and white nights on production launching...
After folowing every How-to and all's documentation over Google, to enable huge pages... i must give you this post.

For enabling huge pages with Linux Debian 6.0.5 on
Linux 2.6.32-5-amd64 #x86_64 GNU/Linux (64Bits)
and MySQL 5.1, you got to add this your /etc/sysctl.conf :

# Total of allowed memory
vm.nr_hugepages = YYYYYY
# total amount of memory that can be allocated to shared memory, huge pages or not, on the box
kernel.shmall = XXXXXXXXXX
# maximum single shared memory segment, which for me was basically innodb_buffer_pool+1%
kernel.shmmax = XXXXXXXXXX
# Groupe autorisé
vm.hugetlb_shm_group = `id -g mysql`

XXXXX is given by this script shell in bash :

##### SCRIPT START #########
#!/bin/bash
# keep 2go memory for system
# (i got 68Go on this one ans 128Go RAM on other one)
keep_for_system=2097152

mem=$(free|grep Mem|awk '{print$2}')
mem=$(echo "$mem-$marge"|bc)
totmem=$(echo "$mem*1024"|bc)
huge=$(grep Hugepagesize /proc/meminfo|awk '{print $2}')
max=$(echo "$totmem*75/100"|bc)
all=$(echo "$max/$huge"|bc)
echo "kernel.shmmax = $max"
echo "kernel.shmall = $all"
######### SCRIPT END #########

check memory usage before reboot by command :
cat /proc/meminfo | grep -i huge

Reboot your system.
and check memory usage again.

It works !
;-)
  Posted by John Anderson on May 13, 2015
A bit of a note on the math here, some articles and blogs say that you should add your innodb_buffer_pool size to your innodb_additional_mem_pool_size, and divide that by your hugetlb page size. Then add a few on to that. Unfortunately, that doesn't seem to be the whole story.

For those who want to allocate as little RAM as possible to HugeTLB while still satisfying the requirements outlined in my.cnf, this formula might be a little better. This is after some experimentation led me to put some effort behind finding out why I always had to allocate many more pages than the math suggested.

The real formula should be:

(innodb_buffer_pool_size in kb +
innodb_additional_mem_pool_size in kb +
tmp_table_size in kb +
innodb_log_buffer_size in kb) / hugetlb size in kb

Then to that, add an additional 11 - 15 pages until MySQL starts. I give my best guess as to why these pages are unaccounted for below.

First, a note on why tmp_table_size is included: I'm not sure if it *should* be tmp_table_size * max_tmp_tables, but MySQL starts and runs with only tmp_table_size included. I think this only applies if default_tmp_storage_engine is InnoDB. If a tmp table needs to be created for a sort or order, and that table is going to be InnoDB in RAM, then hugetlb will need to be used.

Secondly, I noticed in the source code that the InnoDB buffer log uses the 'os_mem_alloc_large' function. So I think that should be included in the calculation as well. In my experimentation, I had 22 pages unaccounted for until I found that, then my unaccounted for pages went down to 11.

As for the pages which don't seem to be accounted for, I think that is the overhead cost of the nature of pages. For instance, if you have an innodb_buffer_pool size of 256 MB, and you have 8 buffer instances then you have:

(268435456 bytes / 8 instances ) = 33554.4 kilobtes to allocate per page.

At 2048 KB per page, that comes to 16.4 pages per buffer. That .4 of a page means an entire page must be allocated, or 17 pages per buffer instead of 16.4. That would account for 8 pages right there. So if one is really picky, declaring buffer sizes that meet the page size exactly would theoretically leave no overhead to absorb. I don't know why but MySQL and google convert have differing opinions on how to convert megabytes to bytes, and vice versa. So if you want to cut it as close as possible, fill out your my.cnf. Start mysql without large-pages, and take note of the values of these 4 variables. Then convert those values into kilobytes for the page count calculation.

Sign Up Login You must be logged in to post a comment.