概要
とある日、postgresが稼働しているサーバのリプレースを行ったところ、
CPUのsysがスパイクしてpostgresが数十秒ほど処理不可となり、ひどい目にあったという話です。
※この環境はCentOS6.8で、postgresは9.4でも8.2でも同現象が発生しました
原因は"THP(Transparent Huge Page)"というOSの機能に関連したdefrag(compaction alloc)処理により、CPUリソースが枯渇したためでした。
検証したところ、以下の状況が重なるとsysスパイク現象が起きてしまう様です。
- サーバの搭載メモリが大きい(たとえば200GB以上)
- 継続的にトランザクションが発生する
- THPが有効である(OSのデフォルトで有効)
THP(Transparent Huge Page)のざっくり説明
通常4KBのページを2MBという大きな単位で扱うことで、
ページ管理コストを削減し、効率改善による性能向上を図ることが目的の機能。
Postgresの場合手動でHugePageを指定できるが、THPはOSが動的(トランスペアレント)にHugePageを割り当てる。
対策
オンラインでTHPのデフラグを停止する
# echo madvise > /sys/kernel/mm/transparent_hugepage/defrag
永続的にTHPのデフラグを停止する(もっとスマートな方法がありそう...)
# vi /etc/rc.local
echo madvise > /sys/kernel/mm/transparent_hugepage/defrag を追記
調査方法
■ 現行設定確認
# cat /sys/kernel/mm/transparent_hugepage/defrag
⇒alwayであれば対象
■ あれ?sys高いなと思ったときに打つ
# perf top
⇒以下のように出たらすぐにTHPのdefrag設定を見直しましょう
~~~
Samples: 2M of event 'cycles', Event count (approx.): 908733026153
42.59% [kernel] [k] compaction_alloc ←★これ (圧縮_再配置)
8.09% [kernel] [k] __reset_isolation_suitable
2.32% [kernel] [k] compact_zone
...
~~~
起きたこと
- CPU使用率のsysが張り付く
- postgresの処理が止まる
- postgresのプロセスが大量生成(セッションが処理されないので)
- PG-REX構成だったのでpacemakerによるF/Oが発生、また発生、またまた発生....
参考:THPにまつわるDB界隈の情報
調べてみると、THPに関してデータベース界隈で情報が見つかりました。個人のまとめとして記載させて頂きます。
・ガチャピン先生こと 小崎資広 大先生のTHPに関するまとめ
・RHEL6マニュアル
「THP はデータベースのワークロードには推奨されません」
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/s-memory-transhuge.html
・Postgresの主要開発者Mr.Robert Haasの記事
「(意訳)CPUのSYSが高負荷になる場合、THPを無効化を推奨している」
http://rhaas.blogspot.jp/2014/03/back-from-lsfmm-and-collab.html
・NTT Data社の大規模環境postgresでの事例
「THPを無効にすることによりCPUのsys高騰が解消した」
http://www.slideshare.net/hadoopxnttdata/ntt-data-postgresql
※エンジニア魂を揺さぶって頂ける素晴らしいスライド
・Oracleマニュアル
「パフォーマンスの問題を回避するために、透過的なHugePagesはすべてのOracle Databaseサーバーで無効にすることをお薦めします」
https://docs.oracle.com/cd/E57425_01/121/CWLIN/memry.htm#CHDFBJAH
・MySQLでの事例
「(意訳)THPはOSの”問題”として劇的な効果を見せた……OFFにしたので安定した」
http://developer.okta.com/blog/2015/05/22/tcmalloc/
※デフォルトのglibc mallocではなく、チューニングでTCMallocを採用したケースのようです
・MongoDB
「(意訳)THPは良いものだがDB処理ではひどい状況になることがある、MongoDBでベストパフォーマンスを保証したければOFFにするべきだ」
https://docs.mongodb.org/manual/tutorial/transparent-huge-pages/
Hadoop
「(意訳)THPはHadoopの処理に深刻なダメージを与える可能性がある」
http://www.cloudera.com/documentation/enterprise/5-2-x/topics/cdh_admin_performance.html
最後に
THPの思想・機能はとても素晴らしいものと考えています。
実際にバイナリデータを多用するトランザクションをpgbenchで負荷がけしたところ、THP有効時とTHP無効時ではCPUのSYSの上がり方が有効時の方が抑えられる結果を得られました。(defrag発生時はsysがスパイクしてしまいますが)
その一方で、OSのバージョンアップを機にデフォルトで有効になったという点で、SYSスパイクトラップとしてその機能を体験してしまったことは、個人として残念な結果でした。。