【メモ】MySQLでのswap発生とNUMAアーキテクチャ
DBサーバでとある日を境にswapが発生していることに気がつきました。
サーバはメモリ32GB搭載していて、そのうちの24GBをinnodb_buffer_pool_sizeに割り当てています。
他のthread毎のメモリ設定値を見てもおかしそうな点はなかったのでググってみました。
MySQL と NUMA アーキテクチャと Swap Insanity
MySQL InnoDBストレージエンジンのチューニング(後編)
なるほど…。
それぞれのCPUがローカルでメモリを管理しているので、
2CPU積んでいるサーバだと、AというCPUで実行されているスレッドが、BというCPUが確保しているメモリ領域にアクセスするには、AのCPUを経由しないといけないわけですね。
このメモリアクセスが不均一になる方式をNUMAアーキテクチャというみたいです。
NUMAアーキテクチャのメモリ管理が、ノードという単位でメモリをCPU毎に分割しているので、
MySQLのinnodb_buffer_pool_sizeのように大量にメモリを割り当てると、
このようになるイメージです。
例えばこの状況で、Node0のメモリばかりが利用されていっぱいになってしまうと、
Node1にまだメモリの空きがあるにも関わらず、swapが発生してしまうというわけです。
この現象を"Swap Insanity"というようです。
今回はこの状態を回避するために、MySQLのメモリ確保のポリシーを変更します。
まずは現状を確認してみる。
# numactl --hardware available: 2 nodes (0-1) node 0 size: 4040 MB node 0 free: 19 MB node 1 size: 4011 MB node 1 free: 22 MB node distances: node 0 1 0: 10 20 1: 20 10
確かにノードは2つ存在しています。
このメモリの偏りを防止するには、メモリ確保のポリシーをinterleave(均一)にする必要があります。
現状のポリシー確認
# numactl --show | grep policy policy: default
defaultのポリシーになっています。
MySQLプロセスのポリシーを確認すると、
defaultになっているのが確認できます。
# cat /proc/{myqslのPID}/numa_maps 2b0ee68c9000 default file=/usr/lib64/libaio.so.1.0.1 mapped=1 N0=1 2b0ee68ca000 default file=/usr/lib64/libaio.so.1.0.1 2b0ee6ac9000 default file=/usr/lib64/libaio.so.1.0.1 anon=1 dirty=1 N0=1 2b0ee6aca000 default anon=3 dirty=3 N0=3 7fff012a1000 default stack anon=16 dirty=16 N0=16
先程のリンクでMySQL5.5でメモリ確保ポリシーをinterleaveにするpatchが公開されているので、
そちらを利用します。
# vim /tmp/mysql55_numa.patch
内容
MySQLを停止させる
/etc/init.d/mysql stop
パッチ適用
# patch -u /usr/bin/mysqld_safe < /tmp/mysql55_numa.patch
MySQLを起動させる
/etc/init.d/mysql start
パッチ適用後の状態確認
# cat /proc/{myqslのPID}/numa_maps 2ba3ed1ca000 interleave=0-1 file=/lib64/libc-2.5.so 2ba3ed3ca000 interleave=0-1 file=/lib64/libc-2.5.so anon=4 dirty=4 N0=2 N1=2 2ba3ed3ce000 interleave=0-1 file=/lib64/libc-2.5.so anon=1 dirty=1 N1=1 2ba3ed3cf000 interleave=0-1 anon=7 dirty=7 N0=3 N1=4 7fffad110000 interleave=0-1 stack anon=17 dirty=17 N0=9 N1=8
第二フィールドがinterleave=0-1になったことが確認できます。
これでSwapが0になればめでたく解決ですが、
稼働中のDBなので、まだ停止させられてません…。
本番で設定でき次第結果を追記します。
以上メモでした。