プログラミング
PostgreSQLとOOM Killer:なぜStrict Memory Overcommitを使用する必要があるのか
PostgreSQL and the OOM Killer: Why You Must Use Strict Memory Overcommit (ubicloud.com)
要約
この記事では、LinuxカーネルのOOM Killer(Out-Of-Memory Killer)がPostgreSQLに壊滅的な影響を与える理由を説明しています。PostgreSQLは共有メモリ構造を持つため、OOM Killerによるプロセスの強制終了はデータ破損のリスクを伴い、サーバー全体のダウンタイムを引き起こす可能性があります。これを防ぐため、著者は「Strict Memory Overcommit」設定の使用を強く推奨し、その設定方法と適切なメモリ制限の決定方法について解説しています。
全文翻訳
PostgreSQLとOOM Killer:なぜStrict Memory Overcommitを使用する必要があるのか
Ubicloud PostgresがGoogle Cloudで利用可能になりました!サインアップはこちらからスターをつけましょうログインサインアップ読み込み中…すべてのブログ投稿すべてのブログ投稿PostgreSQLとOOM Killer:なぜStrict Memory Overcommitを使用するのかUbicloud価格調整ClickHouse PostgreSQL powered by Ubicloud:高速トランザクションと分析オープンソースによるNVIDIA HGX B200 GPUの仮想化スクリーンショットの自動生成によるドキュメントの最新化Vision Language ModelsによるエンドツーエンドOCRハードウェアタッチ、より強力なSSHAIコーディング:冷静なレビューMHzはまだ重要か?推論リクエストのライフ(vLLM V1):LLMはどのように大規模に効率的に提供されるかUbicloud Premium Runners:2倍高速なビルド、10倍大きなキャッシュPostgreSQLパフォーマンス:ローカル vs ネットワーク接続ストレージUbicloud PostgreSQL:新機能、より高いパフォーマンスバースト可能VMの構築:cgroupsによるCPUスライシングベアメタルと同等の価格性能比で、心配無用のKubernetesUbicloudのThin CLIentアプローチコマンドラインインターフェースへのDewey.py:オープンモデルでディープリサーチを再構築Ubicloud Burstable VMは時給0.01ドルからHetznerのデバッグ:powerstat、sensors、dmidecodeを使用した障害の発見クラウド仮想化:Red Hat、AWS Firecracker、Ubicloudの内部構造OpenAI o1 vs. QwQ-32B:分析GitHub ActionsとDockerレイヤーキャッシュを4倍高速にするEuroGPT:ChatGPT Enterpriseのオープンソースでプライバシーを重視した代替手段200行未満のプライベートネットワークピアリングUbicloud上のLantern:PostgreSQLでAIアプリケーションを構築するParadeDB on Ubicloud:完全に管理されたElastic-Qualityフルテキスト検索PostgreSQLのロードバランサー:シンプルでコスト効率が良いRubyでのインフラストラクチャコントロールプレーン構築の13年間自分でPostgresを実行することと他人のために実行することの違いUbicloud Block Storage:暗号化新しいUbicloudコンピューティング機能の発表ARM64 VMの有効化方法Ubicloud Firewalls:Linux Nftablesが柔軟なルールを可能にするLinux Flowtablesによるネットワークパフォーマンスの向上EUの新しいクラウドポータビリティ要件 - それらは何を意味するのか?UbicloudホストArmランナー、価格性能比100倍ビルドブロックストレージをクラウド向けにSPDK(非レプリケート)で構築するオープンでポータブルなPostgres-as-a-serviceシンプルな認証システム(ABAC)構築からの学びvCPU、スレッド、コア、ノード、ソケット。CPU用語は今日どういう意味か?Ubicloudの紹介PostgreSQLとOOM Killer:なぜStrict Memory Overcommitを使用する必要があるのか2026年4月27日 · 10分読むBurak Yucesoyプリンシパルソフトウェアエンジニア私たちのチームメンバーは、過去15年間に5つのマネージドPostgreSQLサービスを構築および運用してきました。それらすべてにおいて、1つの設定は一貫して維持されてきました:strict memory overcommit。このブログ投稿では、strict memory overcommitがデータベースを壊滅的なOOM(out of memory)キルからどのように保護するかを説明します。また、3文字のカーネルバグがこの設定を一時的に無効にせざるを得なかった経緯も共有します。最後に、適切なmemory overcommit制限を決定するための私たちのヒューリスティックについて説明します。うまくいけば、これはあなたのワークロードに適切な設定を見つけるのに役立つでしょう。
なぜPostgreSQLはOOM Killerに耐えられないのかStrict Overcommit:破滅的ではなく、早期に失敗する発見絞り込みフリートワイド分析一文字のバグコミット制限の設定なぜ80%なのかなぜ+2 GBなのか実装結論
なぜPostgreSQLはOOM Killerに耐えられないのか
Linuxでは、プロセスが物理的に利用可能な量を超える仮想メモリを割り当てることができます。プロセスがmalloc()などでメモリを割り当てる場合、カーネルはそのための仮想アドレス空間を予約します。しかし、カーネルはその空間を物理メモリで即座に裏付けません。物理ページは、プロセスが実際にメモリにアクセスしたときにのみ消費されます。
カーネルは、割り当てられたメモリのすべてが同時にアクティブに使用されるわけではないという仮定に依存しています。通常、この仮定は成り立ちます。成り立たない場合、カーネルはメモリを解放するためにOOM killerを呼び出し、プロセスを終了させます。
ほとんどのプロセスにとって、OOM killの処理は簡単です。プロセスは再起動し、再接続し、中断したところから再開します。PostgreSQLは異なります。
PostgreSQLのpostmaster(そのメインのスーパーバイザープロセス)は、接続ごとにバックエンドプロセスをフォークします。これらのバックエンドは、共有バッファ、WALバッファ、ロックテーブル、その他の共有状態を保持するメモリセグメントを共有します。OOM killerはこのアーキテクチャを理解していません。それは単にヒューリスティック(通常は最も多くのメモリを使用しているプロセス)に基づいてプロセスを選択し、それを終了させます。もしそのバックエンドが共有メモリセグメントを変更していた場合、そのセグメントは一貫性のない状態のままになる可能性があります。共有メモリにはOSレベルでのトランザクション保証がありません。共有バッファ内の半書き込みページは、サイレントデータ破損を意味します。
PostgreSQLのpostmasterはこれを認識しています。子プロセスのいずれかがキルされたことを検出すると、最悪の事態を想定します。共有メモリが破損している可能性があります。共有メモリが破損している場合、保存されているデータも破損するリスクがあります。これを防ぐために、postmasterは残りのすべてのバックエンドを終了させます。すべてのアクティブな接続がドロップされます。すべてのインフライトトランザクションが中止されます。次に起動するとき、データベースはクラッシュリカバリを実行します。
これは正しい動作です。PostgreSQLはあなたのデータを保護しています。しかし、それは単一のOOM killが1つの接続に影響するだけではないことを意味します。サーバー上のすべての接続がダウンします。さらに、書き込み量が高かった場合、クラッシュリカバリのためにすべてのWALファイルをリプレイするには時間がかかることがあります。これは、単一のメモリ不足ケースが長時間のダウンタイムを引き起こす可能性があることを意味します。
Strict Overcommit:破滅的ではなく、早期に失敗する
プロセスがメモリを要求したときにカーネルがどのように動作するかを構成することが可能です。Linuxはvm.overcommit_memoryを介して3つのovercommitポリシーを提供しています。
モード0(ヒューリスティック):デフォルトです。カーネルは、システムが現実的に提供できる量(おおよそ空きメモリ+スワップ+回収可能なページキャッシュとスラブ)よりも大きい単一の割り当てを拒否しますが、それ以外の場合は自由にovercommitを許可します。実際には、これは単一のプロセスがシステム全体のメモリよりも多くのメモリを要求するようなばかげた要求のみをブロックします。
モード1(常に):カーネルは、要求されたメモリの量や既にコミットされているメモリ量に関係なく、割り当て要求を拒否しません。すべてのmalloc()とmmap()は成功します。プロセスが後でシステムが実際に提供できる量を超える物理メモリをフォールトインした場合、OOM killerがプロセスを終了させてメモリを解放します。
モード2(Strict):カーネルは、すべてのプロセスにわたるコミットされた仮想メモリの合計をCommitted_ASで追跡し、CommitLimitと呼ばれる上限を強制します。Committed_ASをCommitLimitを超えて増加させる可能性のある割り当ては、ENOMEMで即座に拒否されます。
Strict overcommitでは、カーネルはCommitLimitを設定するための2つのノブ、overcommit_kbytesとovercommit_ratioを持っています。CommitLimitは次のように計算されます。
CommitLimit = overcommit_kbytes + swap
または、overcommit_kbytesが設定されていない場合:
CommitLimit = overcommit_ratio / 100 * available_memory + swap
割り当てがENOMEMエラーコードで失敗した場合。PostgreSQLはこれを優雅に処理します。メモリを割り当てられないバックエンドは、クライアントにエラーを報告し、トランザクションをキャンセルして続行します。postmasterは稼働したままです。他の接続は影響を受けません。これは破滅的なものではなく、日常的なエラーです。トレードオフは、strict overcommitが遅延した破壊的な失敗を早期の優雅な失敗に変換することです。
このトレードオフは、マシンがPostgreSQLと少数の既知のサイドカープロセス専用である場合に最も効果的です。そのシナリオでは、コミットされたメモリプロファイルは予測可能であり、制限は自信を持って調整できます。多様なワークロードを実行する共有マシンでは、コミットされたメモリの予測が困難になります。無関係なプロセスがコミット予算を使い果たす可能性があります。これにより、データベースの負荷は問題ないにもかかわらず、PostgreSQLがENOMEMエラーを受け取る可能性があります。
A Kernel Bug and 648 GB of Phantom Memory
私たちは常にPostgreSQLのためにstrict overcommitを支持してきました。私たちは以前構築したマネージドPostgreSQLサービスやUbicloud PostgreSQLでもそれを使用しました。しかし、今回有効にした後、すぐに問題に遭遇しました。strict memory overcommitをオンにしてから数週間後、私たちは…