MENU

hugepages本番割り当て設計|データベース性能と起動失敗・OOMリスクの事前確認フロー

hugepagesとは、通常の4KiBページサイズよりも大きなメモリページ(x86_64では2MiBまたは1GiB)をOSが管理する仕組みです。データベースのような大容量の共有バッファを持つプロセスにとって、hugepagesの利用はTLB(Translation Lookaside Buffer)ミスの削減に直結するため、CPU使用率の低下とスループットの向上が期待できます。PostgreSQLではhuge_pages = on、MySQLではlarge-pagesオプション、OracleではUSE_LARGE_PAGESパラメータで有効化を宣言します。

しかし本番環境への適用は「設定すれば自動的に恩恵を受けられる」ほど単純ではありません。算出ミス・設定漏れ・THP(Transparent Huge Pages)との競合が重なると、プロセスの起動失敗・OOM Killによる強制終了・予期しないパフォーマンス劣化が発生します。本記事では、背景理解から割り当て量の算出・設定・検証・切り戻しまでを一連のフローとして解説します。

目次

hugepagesがデータベース性能に効く理由と「設定すれば終わり」にならない理由

x86_64のLinuxカーネルは、プロセスの仮想アドレスを物理アドレスに変換するためにTLBキャッシュを使います。4KiBページが標準の環境でPostgreSQLのshared_buffersを32GiBに設定すると、約800万エントリのページテーブルが必要になります。TLBの容量はCPUにより数百〜数千エントリしかないため、ミスが頻発してメモリアクセスごとにページウォークが発生します。これが高負荷時のCPU stealやiostat待ちではない遅延の一因です。

hugepages(2MiB)を使うと同じ32GiBで約16,000エントリに圧縮されます。TLBカバレッジが劇的に改善し、特に大量のランダムアクセスが発生するOLTPワークロードでは効果が顕著です。一方でhugepagesはカーネルが事前予約するため、設定したページ数が実際に用意できない場合や、DBプロセスがその量を要求しきれない場合は起動失敗やメモリ予約失敗になります。「入れたら壊れた」案件の多くはこのギャップが原因です。

本番割り当て前に確認する3つのリスクポイント

設定作業に入る前に、以下の3点を必ずシステム状態と照らし合わせます。

リスク1:hugepages不足による起動失敗

PostgreSQLはhuge_pages = on(デフォルトはtry)の場合、hugepagesが確保できないと起動を拒否します。MySQLも--large-pages時は同様です。割り当てページ数が少なすぎると、冗長構成のフェイルオーバー先でのみ起動失敗が発覚する、という事態も起きます。フェイルオーバー先のサーバーも同じ設定になっているかを事前確認することが不可欠です。

リスク2:hugepages過剰確保によるOOM

hugepagesは確保した時点でスワップ不可の物理メモリが固定されます。システム全体のメモリが16GiBで、hugepagesに14GiBを割り当てると、残り2GiBでOS・監視エージェント・バックアップジョブ・tmpfsなどが競合します。特に月次バッチや定期メンテナンスで一時的にメモリ使用量が増えると、通常プロセスがOOM Killされます。hugepagesの量はDB用途の上限であって、システム全体の空きを削り込む設計は避けます。

リスク3:THP(Transparent Huge Pages)との二重管理

THPはカーネルが自動的に通常ページをhugepagesにまとめる機能で、デフォルトでenabledになっているディストリビューションが多くあります。静的hugepagesと同時に有効だと、割り当て量の計算が複雑になるうえ、THPのcompaction処理がレイテンシスパイクを引き起こすことが知られています。Oracle・PostgreSQL・Redis公式ドキュメントはいずれもTHPの無効化(madviseまたはnever)を推奨しています。hugepages設計を始める前にTHPの現状を確認し、方針を統一します。

# THP現状確認
cat /sys/kernel/mm/transparent_hugepage/enabled
# 推奨設定(madvise: アプリ側でのみTHPを使うモード)
echo madvise | sudo tee /sys/kernel/mm/transparent_hugepage/enabled

hugepages必要量の算出と設定手順

算出の基本は「DBプロセスが要求するShared Memory量 ÷ 2MiB(+ 安全マージン)」です。PostgreSQLを例に取ります。

PostgreSQLの場合

PostgreSQL起動後に以下のコマンドで実際の共有メモリセグメントサイズを確認するのが最も確実です。設定ファイルの計算値より実測値を優先します。

# PostgreSQL起動後に共有メモリキーを確認
sudo -u postgres psql -c "SELECT pg_size_pretty(sum(size)) FROM pg_shmem_allocations;"

# または /proc/PID/smaps から匿名hugepages量を確認
PID=$(pgrep -f "postgres: checkpointer")
grep -i hugepage /proc/$PID/smaps | awk '{sum+=$2} END {print sum/1024 " MiB"}'

得られたMiB値を2MiB(hugepageサイズ)で割り、10〜15%の安全マージンを加えたページ数をvm.nr_hugepagesに設定します。たとえば共有メモリが32,768MiBであれば、32768 ÷ 2 = 16,384ページに安全マージンを加えて17,000前後が目安になります。

sysctl設定と即時反映

# 即時反映(再起動不要)
sudo sysctl -w vm.nr_hugepages=17000

# 永続化
echo "vm.nr_hugepages = 17000" | sudo tee -a /etc/sysctl.d/90-hugepages.conf
sudo sysctl --system

NUMAマルチソケット環境では、NUMAノードごとにvm.nr_hugepages_mempolicyやnumactlでの制御が必要です。ノード間でhugepages確保量に偏りがあると、DBプロセスが特定ノードに偏った際に起動失敗します。numactl --hardwareで構成を確認したうえで各ノードに均等に割り当てます。

設定後の動作検証フロー

設定後は以下の順序で検証します。DB再起動前に確保できているかを必ず確かめます。

# hugepages確保状況の確認
grep -E "HugePages_(Total|Free|Rsvd|Surp)" /proc/meminfo

HugePages_Totalが設定値と一致していない場合、メモリが断片化しており確保できなかった可能性があります。この状態でDBを起動してもhugepagesを使えません。HugePages_Freeがゼロに近い場合は別プロセスが消費しているため調査が必要です。

DB再起動後はHugePages_Rsvd(予約済み)が増加し、HugePages_Freeが減少することを確認します。PostgreSQLであればpg_shmem_allocationsビューでhugepagesが実際に使われているかも確認できます。合わせてperf statやPrometheusのnode_memory_HugePagesメトリクスで事前・事後のTLBミス率を比較すると、性能改善の定量評価が可能です。

切り戻し手順と運用上の注意点

問題が発生した場合の切り戻しはシンプルです。DBプロセスをシャットダウンしてhugepagesを解放し、設定値を戻します。

# DBプロセス停止後にhugepagesを即時解放
sudo sysctl -w vm.nr_hugepages=0
# 永続化ファイルを削除または値を修正
sudo rm /etc/sysctl.d/90-hugepages.conf

注意点として、DBが稼働中にhugepages数を減らすとDBプロセスへの割り当てに影響が出る場合があります。縮小変更は必ずDB停止後に実施します。また、メモリが断片化している環境ではvm.nr_hugepagesを大きな値に設定しても実際に確保されないことがあります。カーネル起動直後(メモリ断片化が最小の状態)に予約するか、vm.nr_hugepagesをGRUBパラメータ(hugepages=N)で指定してブート時に確保するアプローチが信頼性は高くなります。

1GiBページ(1G hugepages)はx86_64のみ対応で、カーネルパラメータhugepagesz=1G hugepages=NをGRUBで指定します。2MiBと異なり実行時の変更はできないため、ブート設定が唯一の変更タイミングです。NUMA環境では特に各ノードへの割り当てを明示する必要があります。

2026年現行環境での差分:RHEL 9・Ubuntu 24.04・systemdの注意点

2026年時点の主要ディストリビューションでは、hugepages関連でいくつか従来と異なる挙動に注意が必要です。

RHEL 9 / AlmaLinux 9 / Rocky Linux 9:デフォルトのTHP設定がmadviseに変更されています。RHEL 8以前の手順書を参照している場合はalwaysと混同しないよう確認が必要です。tuned プロファイル(throughput-performanceやoracle)がTHP・hugepages関連パラメータを上書きする場合があるため、tuned-adm activeでアクティブプロファイルを確認し、カスタムプロファイルで設定を固定します。

Ubuntu 24.04 LTS:systemdのMemoryHugeTLB=ディレクティブがsystemd 253以降で利用可能になっており、サービス単位でhugepages使用量を制限・割り当てできます。cgroupv2 + systemdによるリソース管理が前提の環境では、/etc/sysctl.d/のグローバル設定と組み合わせてサービスファイルでも宣言します。

コンテナ・Kubernetes環境:NodeのHugepages設定はホストOS側で行いますが、Podのresources.limits.hugepages-2Mi指定が必要です。Kubernetesのhugepages機能は1.14でGAになっていますが、ノードのHugepages_Total未満の値しか要求できません。ホストOSの設定とKubernetes Nodeのキャパシティが一致しているかをkubectl describe nodeで必ず確認します。

hugepages設計の要点は「実測値から算出 → THP方針を統一 → NUMAを考慮 → 検証で使用量を確認」という一方向の確認フローを崩さないことです。再起動後に確保量が変わった・フェイルオーバー先だけ起動失敗した、といったトラブルの多くは、この手順のどこかで計算値と実態の乖離を確認せずに進めた結果として発生します。本番適用前のステージング環境での一通りの検証が、後からの修正コストを大幅に下げます。

「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。

ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。

>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)

※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。

PR・広告

新しいLinuxの教科書 第2版(Amazon)

コマンド操作から基本運用までを手を動かして学べる定番書。記事で触れた技術の土台固めに。

Amazonで見る

※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次