無料スクリプト配布のPHP.TO   PHPの実用的なtips PHPマニュアル MySQLマニュアル Apacheマニュアル PostgreSQLマニュアル マニュアル検索    

17.4. カーネルリソースの管理

PostgreSQL は、特に同一システム上で複数のサーバコピーを実行している場合や非常に大規模なインストレーションでは、オペレーティングシステムの様々なリソース制限を超えてしまうことがあります。 本節では、 PostgreSQL で使用されるカーネルリソース、およびカーネルリソース消費に関連した問題を解消する時に取ることができる手順について説明します。

17.4.1. 共有メモリとセマフォ

共有メモリとセマフォはひとまとめに " System V IPC " と呼ばれます (メッセージキューも一緒ですが、これは PostgreSQL とは関係ありません)。 これらの機能を独自の代替的な実装で提供している Windows を除き、 PostgreSQL を実行させるためにはこれらの機能が必要です。

これらの機能の完全な欠落は、サーバ起動時の Illegal system call エラーによって判明します。 その場合はカーネルを設定し直すしかありません。 PostgreSQL はこれらの機能なしでは動きません。 しかし最近のオペレーティングシステムではこうした状況はまれなものです。

PostgreSQL が様々な IPC のハードリミットの1つを超えると、サーバは起動を拒否し、問題および何をすべきかを説明するエラーメッセージを残します。 ( 項17.3.1 も参照してください。) 関係するカーネルパラメータは別々のシステム上でも統一して名付けられています。 表17-1 で概略がわかります。 しかしこれらを設定するための方法は異なります。 以下に、いくつかのプラットフォームへの提案を挙げます。

注意: PostgreSQL 9.3より前では、サーバを起動させるために必要なシステムV共有メモリの量は非常に大きなものでした。 より古いバージョンのサーバで実行しているのであれば、該当するバージョンのサーバの文書を参照してください。

表 17-1. System V IPC パラメータ

名前 説明 適切な値
SHMMAX 共有メモリセグメントの最大サイズ(バイト) 最小でも1キロバイト(複数のサーバのコピーを実行している場合はこれ以上)
SHMMIN 共有メモリセグメントの最小サイズ(バイト) 1
SHMALL 使用可能な共有メモリの総量(バイトまたはページ) バイト指定の場合 SHMMAX と同じです。 ページ指定の場合は ceil(SHMMAX/PAGE_SIZE) です。
SHMSEG プロセスごとの共有メモリセグメントの最大数 必要なのは1セグメントだけですが、デフォルトではもっと多くなっています
SHMMNI システム全体の共有メモリセグメントの最大数 SHMSEG と同様 + 他のアプリケーション用の空間
SEMMNI セマフォ識別子の最大数(つまりセット) 最低 ceil((max_connections + autovacuum_max_workers + 4) / 16)
SEMMNS システム全体のセマフォの最大数 ceil((max_connections + autovacuum_max_workers + 4) / 16) * 17 + 他のアプリケーション用の空間
SEMMSL セットごとのセマフォの最大数 最低17
SEMMAP セマフォマップの中の項目の数 本文を参照
SEMVMX セマフォの最大値 最低1000(デフォルトはしばしば32767ですが、必要がなければ変更しないでください)

PostgreSQL は、サーバのコピー毎にシステムV共有メモリの数バイト(64ビットプラットフォームでは通常48バイト)を必要とします。 最近のほとんどのオペレーティングシステムでは、このくらいの量は簡単に割り当てられます。 しかし複数のサーバのコピーを実行している場合やシステムV共有メモリを使用する他のアプリケーションを実行している場合は、 共有メモリセグメントの最大サイズである SHMMAX をバイト単位で、あるいは、システム全体のシステムV共有メモリである SHMALL を増加させる必要があるかもしれません。 多くのシステムでは SHMALL をバイト単位ではなくページ単位で測ることに注意してください。

問題が少ないのは共有メモリセグメントの最小サイズ( SHMMIN )で、 PostgreSQL では最大でもおよそ32バイトのはずです(通常では1です)。 システム全体のセグメントの最大数( SHMMNI )もしくはプロセスごとのセグメントの最大数( SHMSEG )に関して、使用しているシステムで0に設定されていない限り、問題が起きることはほぼありません。

PostgreSQL は、許可した接続( max_connections )および許可したワーカプロセス( autovacuum_max_workers )ごとに1つのセマフォを使用し、16個のセマフォを一集合として扱います。 この集合それぞれは17個目のセマフォを持ち、そのセマフォは他のアプリケーションに使われているセマフォセットとの衝突を検出するための "マジックナンバー" を持っています。 システム内のセマフォの最大数は SEMMNS によって設定され、その結果としてその値は少なくとも max_connections autovacuum_max_workers と同じ、ただし、許可された接続とワーカ16個ごとに余分な1個を加えた値以上はなければいけません ( 表17-1 の公式を参照してください)。 SEMMNI パラメータはシステム上に同時に存在できるセマフォ集合の数の上限を決定します。 ですからこのパラメータは少なくとも ceil((max_connections + autovacuum_max_workers + 4) / 16) 以上はなくてはいけません。 一時的な失敗の回避策としては許可される接続の数を下げることができますが、 "No space left on device" という紛らわしい言葉が semget() 関数から表示されます。

場合によっては SEMMAP を少なくとも SEMMNS と同程度に増やすことが必要になる場合があるかもしれません。 このパラメータはセマフォリソースマップのサイズを定義し、その中では有効なセマフォのそれぞれの隣接したブロックの項目が必要です。 セマフォ集合が解放されると、解放されたブロックに隣接する既に存在する項目に追加されるか、もしくは新しいマップの項目の下に登録されます。 もしマップが一杯だった場合、解放されたセマフォは(再起動するまで)失われます。 セマフォ空間の断片化により時間が経つごとに、有効なセマフォがあるべき量よりも少なくなる可能性があります。

1つの集合の中にいくつのセマフォがあるかを決める SEMMSL PostgreSQL では少なくとも17はなくてはいけません。

SEMMNU SEMUME のような、その他の様々な "semaphore undo" に関する設定は PostgreSQL には影響を与えません。

AIX

少なくともバージョン5.1では、すべてのメモリが共有メモリとして使用できるように設定されているようにみえますので、 SHMMAX などのパラメータに対して特別な設定は必要ありません。 これは DB/2 などの他のデータベースでも使用される、一般的な設定方法です。

しかし、 /etc/security/limits 内の大域的な ulimit 情報は変更しなければならないかもしれません。 デフォルトのファイルサイズ( fsize )とファイル数( nofiles )用のハードリミットは低過ぎるかもしれないためです。

FreeBSD

でフォルトの設定は sysctl または loader インタフェースを使用して変更を行うことができます。 以下では sysctl を使用してパラメータを変更しています。


#
 
sysctl kern.ipc.shmall=32768


#
 
sysctl kern.ipc.shmmax=134217728


#
 
sysctl kern.ipc.semmap=256

これらの設定をリブートしても永続化するには、 /etc/sysctl.conf を変更します。

残りのセマフォ設定は sysctl では読み取りのみとみなされていますが、 /boot/loader.conf 内で設定することができます。

kern.ipc.semmni=256
kern.ipc.semmns=512
kern.ipc.semmnu=256

これらの値を変更した後、新しい設定を有効にするためにはリブートが必要です。

また、共有メモリをRAM上に残し、スワップへのページアウトを行わせないようにさせたいかもしれません。 これは sysctl kern.ipc.shm_use_phys 設定を使用して実現できます。

sysctl security.jail.sysvipc_allowed を有効にしてFreeBSD jailを実行している場合、異なるjailで実行する postmaster を異なるオペレーティングシステムユーザで実行しなければなりません。 これは、非特権ユーザが別のjailの共有メモリやセマフォに干渉することを防止できるため、セキュリティが向上します。 また、これによりPostgreSQLのIPCを整理するコードを適切に動作させることができます。 (FreeBSD 6.0以降では、IPC整理コードは他のjailにおけるプロセスを適切に検出せず、異なるjailで同一ポートでpostmasterを実行させることができません。)

FreeBSD バージョン4.0以前では、(後述の) OpenBSD と同様に動作します。

NetBSD

NetBSD 以降では、以下の例のようにIPCパラメータを sysctl を用いて調整することができます。


$
 
sysctl -w kern.ipc.shmmax=16777216

この設定をリブートしても永続化させるためには /etc/sysctl.conf を編集してください。

また、共有メモリをRAM上に固定して、スワップのためのページアウトを避けるために、カーネルを設定したいと考えるかもしれません。

5.0より前のバージョンの NetBSD では、(後述の) OpenBSD のように動作します。 ただし、パラメータは option ではなく options キーワードを付けて設定しなければなりません。

OpenBSD

SYSVSHM オプションと SYSVSEM オプションはカーネルのコンパイル時に有効にする必要があります(デフォルトでは有効になっています)。 共有メモリの最大サイズは SHMMAXPGS オプション(ページ数)で決定されます。 以下に様々なパラメータの設定方法の例を示します。

option        SYSVSHM
option        SHMMAXPGS=4096
option        SHMSEG=256

option        SYSVSEM
option        SEMMNI=256
option        SEMMNS=512
option        SEMMNU=256
option        SEMMAP=256

また、共有メモリをRAMの中にロックするようにカーネルを設定することで、スワップにページアウトしないようにもできます。 sysctl を使用して kern.ipc.shm_use_phys を設定することができます。

HP-UX

デフォルトの設定は通常のインストールではほぼ十分です。 HP-UX 10では SEMMNS の出荷時のデフォルトは128ですが、これは大規模なデータベースサイトには低過ぎるかもしれません。

IPC パラメータは システム管理マネージャ SAM )から Kernel Configuration -> Configurable Parameters の下で、設定することができます。 終わったら Create A New Kernel を選択してください。

Linux

デフォルトの最大セグメントサイズは32メガバイト、デフォルトの最大総サイズは2097152ページです。 "大規模ページ" を持つ通常ではないカーネル設定を除き、1ページはほとんど常に4096バイトです。 (検証には getconf PAGE_SIZE を使用してください。)

共有メモリサイズの設定は sysctl インタフェースを使用して変更可能です。 例えば16ギガバイトまで許すには以下のようにします。


$
 
sysctl -w kernel.shmmax=17179869184


$
 
sysctl -w kernel.shmall=4194304

更にこれらの設定をリブート時に保持できるように /etc/sysctl.conf に保存することができます。 こうすることを大いに勧めます。

古めのディストリビューションでは sysctl プログラムが存在しない可能性があります。 この場合、 /proc ファイルシステムに対する操作で同等の変更を行うことができます。


$
 
echo 17179869184 >/proc/sys/kernel/shmmax


$
 
echo 4194304 >/proc/sys/kernel/shmall

他のデフォルトはかなり豊富なサイズですので、通常は変更する必要はありません。

Mac OS X

OS Xにおける共有メモリの推奨設定方法は、以下のような変数代入文からなる /etc/sysctl.conf という名称のファイルを作成することです。

kern.sysv.shmmax=4194304
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=1024

一部のバージョンのOS Xでは /etc/sysctl.conf 内に共有メモリパラメータ 5つすべて を設定しなければならないという点に注意してください。 さもなくば値が無視されます。

最近のリリースのOS Xは、 SHMMAX を4096の倍数以外に設定しようとすると無視しますので、注意してください。

このプラットフォームでは SHMALL は4キロバイトページ単位です。

古めのバージョンのOS Xでは、共有メモリパラメータの変更を有効にするためにリブートが必要になります。 10.5から SHMMNI 以外の変更は、 sysctl を用いることにより、その場で行うことができます。 しかしいずれにせよ /etc/sysctl.conf 経由で望む値に設定することが最善です。 リブートを行っても値が保持されるからです。

/etc/sysctl.conf はOS X 10.3.9以降でのみ使用されます。 もしこれより前の10.3.xリリースを使用しているのであれば、 /etc/rc ファイルを編集し、以下のコマンドで値を変更しなければなりません。

sysctl -w kern.sysv.shmmax
sysctl -w kern.sysv.shmmin
sysctl -w kern.sysv.shmmni
sysctl -w kern.sysv.shmseg
sysctl -w kern.sysv.shmall

通常 /etc/rc はOS Xのアップデートで上書きされることに注意してください。 ですので、アップデートの度に編集し直す必要があるものと考えなければなりません。

OS X 10.2以前では、代わりに /System/Library/StartupItems/SystemTuning/SystemTuning ファイル内にあるこれらのコマンドを編集してください。

SCO OpenServer

デフォルトの設定では、セグメント当たり512キロバイトの共有メモリが許されています。 この設定を増加させるには、まず、 /etc/conf/cf.d ディレクトリに移動します。 SHMMAX の現在値を表示させるには、以下を実行します。

./configure -y SHMMAX

SHMMAX に新しい値を設定するには以下を実行します。

./configure SHMMAX=

value

ここで、 value が希望する新しい値(バイト単位)です。 そして、以下のようにカーネルを再構築し、リブートします。

./link_unix

Solaris 2.6から2.9 (Solaris 6からSolaris 9)

必要な設定は /etc/system で変えることができ、例えば以下のようになります。

set shmsys:shminfo_shmmax=0x2000000
set shmsys:shminfo_shmmin=1
set shmsys:shminfo_shmmni=256
set shmsys:shminfo_shmseg=256

set semsys:seminfo_semmap=256
set semsys:seminfo_semmni=512
set semsys:seminfo_semmns=512
set semsys:seminfo_semmsl=32

変更を反映させるには再起動する必要があります。 古めのバージョンのSolarisにおける共有メモリの情報は http://sunsite.uakom.sk/sunworldonline/swol-09-1997/swol-09-insidesolaris.html を参照してください。

Solaris 2.10 (Solaris 10)以降
OpenSolaris

Solaris 10以降とOpenSolarisでは、デフォルトの共有メモリとセマフォ設定は大抵の PostgreSQL アプリケーションで十分あります。 Solarisのデフォルトの SHMMAX はシステムの RAM の1/4になりました。 さらにこの設定を調整するためには、 postgres ユーザに関するプロジェクト設定を使用しなければなりません。 例えば以下を root 権限で実行してください。

projadd -c "PostgreSQL DB User" -K "project.max-shm-memory=(privileged,8GB,deny)" -U postgres -G postgres user.postgres

このコマンドは user.postgres プロジェクトを追加し、 postgres ユーザの共有メモリの最大サイズを8GBに設定します。 この影響は次にこのユーザがログインした時、または PostgreSQL を再起動した時(再読み込み時ではありません)に有効になります。 上では PostgreSQL postgres グループに属する postgres ユーザにより実行されていることを前提としています。 サーバの再起動は不要です。

多くの接続を受け付けるデータベースサーバにおいて推奨するカーネル設定にはこの他に以下があります。

project.max-shm-ids=(priv,32768,deny)
project.max-sem-ids=(priv,4096,deny)
project.max-msg-ids=(priv,4096,deny)

さらに、ゾーン内で PostgreSQL を実行している場合、ゾーンのリソース使用上限も上げる必要があるかもしれません。 projects prctl については System Administrator's Guide の第2章 プロジェクトとタスクを参照してください。

UnixWare

UnixWare 7では、共有メモリセグメントの最大サイズはデフォルト設定で512キロバイトです。 現在の SHMMAX 値を表示するためには下記を実行してください。

/etc/conf/bin/idtune -g SHMMAX

これは現在値、デフォルト値、最小値、および最大値を、バイト単位で表示します。 SHMMAX の新しい値を設定するためには、以下を実行します。

/etc/conf/bin/idtune SHMMAX 

value

ここで value は、希望する新しい値(バイト)です。 SHMMAX の設定が終わったらカーネルを再構築し、リブートします。

/etc/conf/bin/idbuild -B

17.4.2. リソースの制限

Unixライクなオペレーティングシステムでは PostgreSQL サーバの操作と関係する可能性のある様々な種類のリソース制限があります。 特に重要なのは、ユーザごとのプロセス数の制限、プロセスごとのオープンファイルの数、プロセスごとの利用可能なメモリの量です。 これらのそれぞれが "ハード" "ソフト" の2つの制限を持っています。 ソフト制限が実際に有効な制限ですが、ユーザによってハード制限まで変えることが可能です。 ハード制限はrootユーザによってのみ変えることができます。 setrlimit システムコールがこれらのパラメータの設定を行います。 シェルの組み込みコマンド ulimit (Bourne シェル)もしくは limit csh )は、コマンドラインからリソース制限を制御するために使われます。 BSD派生システム上では /etc/login.conf ファイルが、ログイン時に設定される様々なリソース制限を制御します。 詳細はオペレーティングシステムの文書を参照してください。 関連するパラメータは maxproc openfiles datasize です。 以下に例を示します。

default:\
...
        :datasize-cur=256M:\
        :maxproc-cur=256:\
        :openfiles-cur=256:\
...

-cur はソフト制限です。 ハード制限を設定するためには -max を付けてください。)

カーネルはいくつかのリソースに対して、システム全体の制限も持つことができます。

  • Linux では、 /proc/sys/fs/file-max が、カーネルがサポートするオープンファイル数の最大を決定します。 この数を変えるためには、そのファイルに別の数を書き込むか、あるいは /etc/sysctl.conf に代入式を追加します。 プロセスごとのファイルの最大制限はカーネルがコンパイルされた時に固定されます。 詳しい情報については /usr/src/linux/Documentation/proc.txt を参照してください。

PostgreSQL サーバは接続ごとに1つのプロセスを使うので、少なくとも許可された接続の数だけのプロセスに残りのシステムで必要な分を追加したものが必要になります。 通常はこれは問題ではありませんが、1つのマシン上でいくつかのサーバを起動している場合は厳しい状況になるかもしれません。

オープンファイルの制限の出荷時のデフォルトは、しばしば大多数のユーザはマシン上でシステムリソースの不正使用をしないという前堤に立った "社会的に友好的な" 値を設定してしまいます。 もし1つのマシン上で複数のサーバを起動する場合はそれが必要でしょうが、専用サーバではこの制限を上げたいかもしれません。

反対に、個々のプロセスが多数のファイルをオープンすることを許可するシステムもあります。 そのようなプロセスが数個以上あれば、システム全体の制限は簡単に超えてしまいます。 この発生を検知し、システム全体の制限の変更を望まない場合は、 PostgreSQL max_files_per_process 設定パラメータを設定し、オープンファイルの消費を制限することができます。

17.4.3. Linuxのメモリオーバーコミット

Linux 2.4以降では、デフォルトの仮想メモリの動作は PostgreSQL には最適ではありません。 カーネルがメモリオーバーコミットを実装する方法のため、カーネルは、 PostgreSQL や他のプロセスのメモリ要求がシステムの仮想メモリを枯渇させた場合、 PostgreSQL postmaster (マスターサーバプロセス)を終了させる可能性があります。

これが発生した場合、以下のようなカーネルメッセージが現れます (こうしたメッセージを検索する場所についてはシステム文書と設定を参照してください)。

Out of Memory: Killed process 12345 (postgres).

これは、 postgres プロセスがメモリ不足のために終了してしまったことを示します。 起動中のデータベース接続は正常に動作しますが、新しい接続は受け付けられません。 復旧するには、 PostgreSQL を再起動しなければなりません。

この問題を防止する1つの方法として、 PostgreSQL を他のプロセスがそのマシンのメモリを枯渇させないことが確実なマシンで起動するというものがあります。 物理メモリとスワップ領域が消費尽くされた時のみにメモリ不足(OOM)キラーが発生するため、メモリが不足する場合、オペレーティングシステムのスワップ領域を増やすことが問題解決の役にたちます。

PostgreSQL 自体が実行中のシステムのメモリ不足を引き起こした場合、設定を変更することで問題を防止することができます。 メモリ関連の設定パラメータ、具体的には shared_buffers および work_mem 、を低くすることで回避できる場合もあります。 個の他にもデータベースサーバ自体への接続が多く許可しすぎることで問題が引き起こされる場合もあります。 多くの場合、 max_connections を減らし、外部のコネクションプールソフトウェアを使用することで改善されます。

Linux 2.6以降では、メモリを "オーバーコミット" させないようにカーネルの動作を変更することができます。 この設定は完全に OOMキラー の発生を防ぐことはできませんが、その発生頻度をかなり軽減しますので、システム動作の堅牢性をより高めます。 これは、以下のように sysctl を使用して厳密なオーバーコミットモードを選択すること、もしくは、 /etc/sysctl.conf に同等の項目を記述することで実施されます。

sysctl -w vm.overcommit_memory=2

また、関連する vm.overcommit_ratio 設定を変更した方が良いでしょう。 詳細は Documentation/vm/overcommit-accounting カーネル文書を参照してください。

vm.overcommit_memory の変更と関係なく使用できるその他の方法は、プロセス固有の oom_score_adj 値をpostmasterプロセス向けに -1000 に設定することです。 これによりOOMキラーの対象とならないことが保証されます。 このための最も簡単な方法は以下をpostmasterの起動スクリプト内でpostmasterを実行する直前に実行することです。

echo -1000 > /proc/self/oom_score_adj

この作業をrootで実行しなければならないことに注意して下さい。 さもないと効果がありません。 このためrootが所有する起動スクリプトがこれを行うためには最も簡単な場所です。 こうした場合、 PostgreSQL の構築時に -DLINUX_OOM_SCORE_ADJ=0 CPPFLAGS に追加したいと考えるでしょう。 これによりpostmasterの子プロセスは通常のゼロという oom_score_adj で実行されるようになり、必要に応じてOOMキラーの対象となりえます。

古いLinuxカーネルは /proc/self/oom_score_adj を提供していませんが、同様の機能を持つ /proc/self/oom_adj があるでしょう。 これは、無効にするための設定値が -1000 ではなく -17 であるという点を除いては同じように動作します。 相当する PostgreSQL のビルドフラグは -DLINUX_OOM_ADJ=0 です。

注意: Linux 2.4カーネルのベンダの中には、2.6のオーバーコミット sysctl 版を持つものがあることが報告されています。 しかし、関係するコードを持たない2.4カーネルで vm.overcommit_memory を2に設定することはより状況を悪化させます。 2.4のインストレーションではこれを試す前に、実際のカーネルソースコードを調査し、その中でサポートしているかどうかを検証することをお勧めします( mm/mmap.c ファイル内の vm_enough_memory 関数を参照してください)。 overcommit-accounting 文書ファイルの存在は、この機能が存在するかどうかを証明するものでは ありません 。 疑わしい場合は、使用中のカーネルベンダのカーネル専門家に相談してください。


powered by SEO.CUG.NET