InnoDB大メモリページの有効化

20388 ワード

Linuxオペレーティング・システムでメモリ要件の大きいアプリケーションを実行する場合、デフォルトのページ・サイズが4 KBであるため、TLB Missや欠落したページの割り込みが多くなり、アプリケーションのパフォーマンスに大きく影響します.オペレーティングシステムが2 MB以上をページング単位として使用する場合、TLB Missとページング欠落中断の数が大幅に減少し、アプリケーションのパフォーマンスが大幅に向上します.これもLinuxカーネルが大きなページサポートを導入した直接的な原因です.利点は明らかで、アプリケーションが2 MBのメモリを必要とすると仮定し、オペレーティングシステムが4 KBをページング単位とする場合、512ページが必要であり、さらにTLBには512個のテーブル項目が必要であり、同時に512個のページ項目が必要であり、オペレーティングシステムは少なくとも512回のTLB Missと512回の欠ページ中断を経験してこそ、2 MBアプリケーション空間をすべて物理メモリにマッピングすることができる.しかしながら、オペレーティングシステムが2 MBをページングの基本単位として採用する場合、TLB Missと欠ページ割り込みを1回だけ必要とし、2 MBのアプリケーション空間に虚実マッピングを確立し、実行中にTLB Missと欠ページ割り込みを経験する必要はない(TLBエントリ置換とSwapが発生していないと仮定する).
Linuxオペレーティングシステムは、最小のコストで大きなページサポートを実現するために、hugetlbfsベースの特殊ファイルシステム2 Mバイトの大きなページサポートを採用しています.このような特殊なファイルシステム形式で大きなページをサポートすることにより、アプリケーションは必要に応じて2 MBの大きなページを強制的に使用することなく、虚存ページサイズを柔軟に選択することができる.
mysqlではinnodbはlarge pagesを使用してbuffer poolとadditional memory poolを割り当てることができる.次にmysqlがlarge pagesを用いた具体的な実装方法を見る.
1:システムがhuge-pagesをサポートしているかどうかを確認する
[root@localhost ~]# cat /proc/meminfo | grep -i huge
AnonHugePages:  47708160 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
[root@localhost ~]# 

Hugepagesizeの値は、システムがlarge pagesをサポートしていることを示しています(サポートされていない場合は、システムが再コンパイルしてサポートする必要があります).
2.事前に割り当てられたhugepagesサイズの変更
[root@localhost ~]# sysctl -w vm.nr_hugepages=512
vm.nr_hugepages = 512
[root@localhost ~]# 
[root@localhost ~]# cat /proc/meminfo | grep -i huge
AnonHugePages:     79872 kB
HugePages_Total:     512
HugePages_Free:      505
HugePages_Rsvd:      229
HugePages_Surp:        0
Hugepagesize:       2048 kB
[root@localhost ~]# 

3.mysqlユーザーのグループ情報の表示
[root@localhost ~]# id mysql
uid=500(mysql) gid=501(mysql) groups=501(mysql)
[root@localhost ~]# 

4.大ページメモリを使用するユーザー・グループの構成
[root@localhost ~]# sysctl -w  vm.hugetlb_shm_group=501
vm.hugetlb_shm_group = 501
[root@localhost ~]# 

5.ulimitの修正
vim /etc/security/limits.conf
@mysql soft memlock unlimited
@mysql hard memlock unlimited

6.修正/etc/sysconfig.conf
# Increase the amount of shmem allowed per segment
# This depends upon your memory, remember your
kernel.shmmax = 68719476736
# Increase total amount of shared memory.
kernel.shmall = 4294967296

shmmaxは最大の共有メモリセグメントのサイズで、単位はバイトで、デフォルトの32 Mで、きっと足りないで、これはinnodb_よりbuffer_poolは大きいです.shmallは共有メモリの合計サイズで、単位はページで、デフォルトは2097152(8 G)です.sysctl-wまたは/etc/sysctlを用いることができる.confで設定します.
Sysctl-pは、その設定を有効にします.
7.修正my.cnf
[mysqld]
large-pages

8.mysqlを再起動する
[root@localhost mysql]# /etc/init.d/mysqld restart
Shutting down MySQL.                                       [  OK  ]
Starting MySQL....                                         [  OK  ]
[root@localhost mysql]# cat localhost.localdomain.err 
140320 15:18:12 [Note] /usr/local/mysql/bin/mysqld: Normal shutdown

140320 15:18:12 [Note] Event Scheduler: Purging the queue. 0 events
140320 15:18:12  InnoDB: Starting shutdown...
140320 15:18:12  InnoDB: Shutdown completed; log sequence number 3629001490
140320 15:18:12 [Note] /usr/local/mysql/bin/mysqld: Shutdown complete

140320 15:18:12 mysqld_safe mysqld from pid file /data/mysql/localhost.localdomain.pid ended
140320 15:18:13 mysqld_safe Starting mysqld daemon with databases from /data/mysql
140320 15:18:13 InnoDB: The InnoDB memory heap is disabled
140320 15:18:13 InnoDB: Mutexes and rw_locks use GCC atomic builtins
140320 15:18:13 InnoDB: Compressed tables use zlib 1.2.3
140320 15:18:13 InnoDB: Initializing buffer pool, size = 256.0M
140320 15:18:13 InnoDB: Completed initialization of buffer pool
140320 15:18:13 InnoDB: highest supported file format is Barracuda.
140320 15:18:15  InnoDB: Waiting for the background threads to start
140320 15:18:16 InnoDB: 1.1.8 started; log sequence number 3629001490
140320 15:18:16 [Note] Server hostname (bind-address): '0.0.0.0'; port: 3306
140320 15:18:16 [Note]   - '0.0.0.0' resolves to '0.0.0.0';
140320 15:18:16 [Note] Server socket created on IP: '0.0.0.0'.
140320 15:18:16 [Note] Event Scheduler: Loaded 0 events
140320 15:18:16 [Note] /usr/local/mysql/bin/mysqld: ready for connections.
Version: '5.5.25a-log'  socket: '/tmp/mysqld.sock'  port: 3306  Source distribution

nrを小さくしたら間違いがないのが見えますhugepagesは200を見てみましょう
[root@localhost mysql]# sysctl -w vm.nr_hugepages=200
vm.nr_hugepages = 200
[root@localhost mysql]# /etc/init.d/mysqld restart
Shutting down MySQL.                                       [  OK  ]
Starting MySQL...                                          [  OK  ]
[root@localhost mysql]# cat localhost.localdomain.err 
140320 15:20:08 [Note] /usr/local/mysql/bin/mysqld: Normal shutdown

140320 15:20:08 [Note] Event Scheduler: Purging the queue. 0 events
140320 15:20:08  InnoDB: Starting shutdown...
140320 15:20:08  InnoDB: Shutdown completed; log sequence number 3629001490
140320 15:20:08 [Note] /usr/local/mysql/bin/mysqld: Shutdown complete

140320 15:20:08 mysqld_safe mysqld from pid file /data/mysql/localhost.localdomain.pid ended
140320 15:20:09 mysqld_safe Starting mysqld daemon with databases from /data/mysql
140320 15:20:09 InnoDB: The InnoDB memory heap is disabled
140320 15:20:09 InnoDB: Mutexes and rw_locks use GCC atomic builtins
140320 15:20:09 InnoDB: Compressed tables use zlib 1.2.3
140320 15:20:09 InnoDB: Initializing buffer pool, size = 256.0M InnoDB: HugeTLB: Warning: Failed to allocate 274726912 bytes. errno 12 InnoDB HugeTLB: Warning: Using conventional memory pool 140320 15:20:09 InnoDB: Completed initialization of buffer pool
140320 15:20:09 InnoDB: highest supported file format is Barracuda.
140320 15:20:11  InnoDB: Waiting for the background threads to start
140320 15:20:12 InnoDB: 1.1.8 started; log sequence number 3629001490
140320 15:20:12 [Note] Server hostname (bind-address): '0.0.0.0'; port: 3306
140320 15:20:12 [Note]   - '0.0.0.0' resolves to '0.0.0.0';
140320 15:20:12 [Note] Server socket created on IP: '0.0.0.0'.
140320 15:20:12 [Note] Event Scheduler: Loaded 0 events
140320 15:20:12 [Note] /usr/local/mysql/bin/mysqld: ready for connections.
Version: '5.5.25a-log'  socket: '/tmp/mysqld.sock'  port: 3306  Source distribution
[root@localhost mysql]# 

次の警告が表示されます.
InnoDB: HugeTLB: Warning: Failed to allocate 274726912 bytes. errno 12
InnoDB HugeTLB: Warning: Using conventional memory pool

hugepageがメモリを割り当てる場合、使い捨てで独占的であるため、使い捨てとはmysqldが起きると、すべてのbuffer poolに必要なメモリの合計が一度に割り当てられ、これらの割り当てられたメモリが他のプロセスに占有されないことを意味する.だから使い捨てで独占です.buffer poolに必要なメモリが一度に割り当てられると、必然的にswapは使用されません.using conventional memory poolってどういう意味ですか?あなたのhugepageメモリはあなたのbuffer poolサイズに足りないので、通常のメモリを使います.
 
大きなページのメモリを開くメリット:
1.メモリディスプレイスメントの削減
2.TLB miss回数を減らす
3.swapを減らす
 
mysqlを起動するときに最も報告しやすいエラーは、次のとおりです.
InnoDB: HugeTLB: Warning: Failed to allocate 274726912 bytes. errno 12InnoDB HugeTLB: Warning: Using conventional memory pool
これは、上記の2点によるものです.1)nr_hugepagesの値*2 Mは(innodb_buffer_pool_size+innodb_additional_mem_pool_size)より大きいべきである.innodbはlarge pagesを使用してbuffer poolとadditional memory poolを割り当てることができるからである.2)memlockの設定は、mysqlを起動する際に必ずulimit-aでmax locked memoryの設定が妥当かどうかを確認し、以上の2つの方法で設定してみてください.もう一つ、/etc/security/limits.confプロファイルの変更
 
参考資料:
http://www.cyberciti.biz/tips/linux-hugetlbfs-and-mysql-performance.html
https://dev.mysql.com/doc/refman/5.0/en/large-page-support.html