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

大きな PostgreSQL のインストレーションになると、オペレーティングシステムのリソースの限界を容易に越えてしまいます (システムによっては出荷時のデフォルトが低すぎるため"大きな"インストレーションの要望にも応えられません)。このような問題に遭遇したことがある場合は、この先を読んでください。

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

共有メモリとセマフォはひとまとめにして"System V IPC"と呼ばれます(メッセージキューとも一緒ですが、PostgreSQLでは関係ありません)。 ほとんどすべての現代のオペレーティングシステムはこれらの機能を提供しますが、特にBSDの痕跡を引きずるシステムのように、すべてがデフォルトで有効にされたり適当なサイズになっているわけではありません(QNXBeOSにおける移植では、PostgreSQLはこれらの機能の独自の代替実装を提供しています)。

これらの機能の完全な欠落はIllegal system callエラーでpostmaster起動時に表示されます。その場合はカーネルを設定し直すしかありません。 PostgreSQLはこれらの機能なしでは動きません。

PostgreSQL がさまざまな IPC のハードリミットの 1 つを越えると、postmaster は起動を拒否し、発生した問題とおよび何をすべきかを説明するエラーメッセージを残します (Section 3.3.1 も参照してください)。関係するカーネルパラメータは別々のシステム上でも統一して名付けられています(Table 3-3で概略がわかります)。 しかしこれらを設定するための方法は異なります。 以下に、いくつかのプラットフォームへの提案を挙げます。これらの設定を変えるには、しばしばマシンを再起動することが必要になり、カーネルをコンパイルし直す必要がある場合さえあるので注意してください。

Table 3-3. System V IPCパラメータ

名前説明適切な値
SHMMAX共有メモリセグメントの最大サイズ(バイト)250 kB + 8.2 kB * shared_buffers + 14.2 kB * max_connections または無限大
SHMMIN共有メモリセグメントの最小サイズ(バイト)1
SHMALL使用可能な共有メモリの総量(バイトまたはページ)バイト指定の場合 SHMMAX と同じです。 ページ指定の場合は ceil(SHMMAX/PAGE_SIZE)です。
SHMSEGプロセスごとの共有メモリセグメントの最大数必要なのは1セグメントだけですが、デフォルトではもっと多くなっています
SHMMNIシステム全体の共有メモリセグメントの最大数SHMSEGと同様 + 他のアプリケーション用の空間
SEMMNIセマフォ識別子の最大数(つまりセット)>= ceil(max_connections / 16)
SEMMNSシステム全体のセマフォの最大数ceil(max_connections / 16) * 17 + 他のアプリケーション用の空間
SEMMSLセットごとのセマフォの最大数>= 17
SEMMAPセマフォマップの中の項目の数テキストを参照
SEMVMXセマフォの最大値>= 255(デフォルトはしばしば32,767ですが、変更するようにいわれない限り変えないでください)

一番重要な共有メモリのパラメータは、共有メモリセグメントの最大サイズのバイト数 SHMMAX です。もし shmget から Invalid argument のようなエラーメッセージを受けた場合、この上限を越えている可能性があります。 要求される共有メモリセグメントのサイズは要求されるバッファ数(オプション -B)と許されている接続数(オプション -N)によりますが、前者の方が重要です(一時的な策として、エラーをなくすためにこれらの設定を低くすることもできます)。大雑把な概算としては、必要とされるセグメントサイズをバッファ数×ブロック数(デフォルトでは8Kバイト)+十分なオーバヘッド(少なくとも0.5Mバイト)です。表示されるすべてのエラーメッセージには割り当てに失敗したメモリサイズが表示されているはずです。

問題が少ないのは共有メモリセグメントの最小サイズ(SHMMIN)で、PostgreSQL では最大でも 256K バイトのはずです(通常では 1 です)。システム全体のセグメントの最大数(SHMMNI)もしくはプロセスごとのセグメントの最大数(SHMSEG)は使用しているシステムで0に設定されていない限り問題はないはずです。システムによっては共有メモリの合計値にも制限を設定しています。 下記のプラットフォーム固有の指示を参照してください。

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

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

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

SEMMNUSEMUMEのような、その他のさまざまな"semaphore undo"に関する設定はPostgreSQLでは問題にする必要がありません。

BSD/OS

共有メモリ. デフォルトでは、4Mバイトの共有メモリしかサポートされていません。共有メモリはページングできないことを覚えておいてください。 RAMの中にロックされているのです。postmaster でサポートされる共有バッファ数を増加するには、カーネルパラメータファイルに以下を追加して下さい。 SHMALL の 1024 という値は、共有メモリが 4MB であることを示します。以下では、最大の共有メモリ領域を 32MB まで増加しています。

options "SHMALL=8192"
options "SHMMAX=\(SHMALL*PAGE_SIZE\)"

4.1以降のものを使っている場合は、ただ上の変更を行い、カーネルをコンパイルし直し、再起動してください。それ以前のものを使っている方は、現在のカーネルのsysptsize値を見つけるためbpatchを使ってください。これは起動時に動的に計算されます。

$ bpatch -r sysptsize
0x9 = 9

次に、カーネル設定ファイルに SYSPTSIZEをハードコーディングした値として追加して下さい。bpatchを使用して見つけた値を増加して下さい。希望する共有メモリを4Mバイト増加させるごとに、1増加させてください。

options "SYSPTSIZE=16"

sysptsizeは、sysctlによって変えることはできません。

セマフォ. セマフォの数を増やす必要がある場合があるかもしれません。デフォルトではPostgreSQLは34のセマフォを割り当てていますが、これはシステム合計のデフォルトである60の半分以上です。

カーネル設定ファイルの中に必要な値を設定してください。 たとえば下記のようになります。

options "SEMMNI=40"
options "SEMMNS=240"
options "SEMUME=40"
options "SEMMNU=120"

FreeBSD
NetBSD
OpenBSD

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

options         SYSVSHM
options         SHMMAXPGS=4096
options         SHMSEG=256

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

(実際は NetBSDOpenBSD では、このキーワードは単数形のoption です。

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

HP-UX

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

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

Linux

共有メモリ制限のデフォルト(SHMMAXSHMALLの両方とも)は2.2カーネルで32Mバイトですが、procファイルシステムで変えることができます(再起動なし)。たとえば128Mバイトを許可するためには下記のようになります。

$ echo 134217728 >/proc/sys/kernel/shmall
$ echo 134217728 >/proc/sys/kernel/shmmax

これらのコマンドは起動時に実行されるスクリプトに書いておくことができます。

これらのパラメータを制御するために、もし有効であればsysctlを代わりに使うこともできます。/etc/sysctl.confというファイルを探し、以下の2行をそれに追加してください。

kernel.shmall = 134217728
kernel.shmmax = 134217728

このファイルは通常は起動時に処理されますが、sysctlは後で明示的に呼び出すこともできます。

他のパラメータはどんなアプリケーションにも合うようなサイズに設定されています。自分で確認したい場合は、/usr/src/linux/include/asm-xxx/shmpara m.h/usr/src/linux/include/linux/sem.h を参照してください。

OS/X

/System/Library/StartupItems/SystemTuning/SystemTuning ファイルを編集して以下の値を変更します。

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

これらの値は OS/X 上で、上述のオペレーティングシステムでリストしたものと同じ意味を持ちます。

SCO OpenServer

デフォルトの設定では、セグメントごとに512Kバイトの共有メモリしか許可されていませんが、これは-B 24 -N 12にはほぼ十分です。設定を増やすためには、まず /etc/conf/cf.d ディレクトリに移動してください。現在のSHMMAX値をバイトで表示するためには下記を実行してください。

./configure -y SHMMAX

SHMMAX の新しい値を設定するためには、

./configure SHMMAX=value

value は、使おうとしている新しい値 (バイト) です。SHMMAXの設定が終わったらカーネルのビルドをし直します。

./link_unix

その後再起動してください。

Solaris

少なくともバージョン 2.6 では、共有メモリセグメントのデフォルトの最大サイズは PostgreSQL には低すぎる設定になっています。必要な設定は/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://www.sunworld.com/swol-09-1997/swol-09-insidesolaris.htmlも参照してください。

UnixWare

UnixWare 7では、共有メモリセグメントの最大サイズはデフォルト設定で512Kバイトです。これは-B 24 -N 12にはおよそ十分です。現在のSHMMAX値を表示するためには下記を実行してください。

/etc/conf/bin/idtune -g SHMMAX

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

/etc/conf/bin/idtune SHMMAX value

value は、使おうとしている新しい値 (バイト) です。SHMMAXの設定が終わったらカーネルのビルドをし直します。

/etc/conf/bin/idbuild -B

その後再起動してください。

3.5.2. リソースの制限

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

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

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

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

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

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

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