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

大きなPostgresのインストールはオペレーティング システムのリソースリミットを容易に越えてしまいます。(システムに よっては出荷時のデフォルトが低すぎるため"大きな"インストール の必要さえありません。)このような問題に遭遇したことがある方は この先を読んでください。

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

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

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

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

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

名前説明適当な値
SHMMAX共有メモリセグメントの最大サイズ(バイト)512 kB + 8192 * バッファ数 + その他 ... 無限大
SHMMIN共有メモリセグメントの最小サイズ(バイト)1 (最大で 256 kB)
SHMSEGプロセスごとの共有メモリセグメントの最大数必要なのは 1 セグメントだけですが、デフォルトでは もっと多くなっています
SHMMNIシステム全体の共有メモリセグメントの最大数SHMSEGと同様 + 他のアプリケーション用の空間
SEMMNIセマフォ識別子の最大数 (つまりセット)>= ceil(max_connections / 16)
SEMMNSシステム全体のセマフォの最大数ceil(max_connections / 16) * 17 + 他のアプリケーション用の空間
SEMMSLセットごとのセマフォの最大数>= 17
SEMMAP セマフォマップの中の項目の数テキスト参照
SEMVMXセマフォの最大値>= 255 (デフォルトはしばしば 32767 ですが、そう するように言われない限り変えないでください)

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

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

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

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

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

SEMMNU and SEMUMEのような、 その他の様々な"semaphore undo"に関する設定は Postgresでは問題にする必要がありません。

BSD/OS

共有メモリ. デフォルトでは、4MB の共有メモリしかサポートされていません。 共有メモリはページングできないことを覚えておいて下さい。 RAM の中にロックされているのです。共有メモリのパラメータ は以下です。


#define SHMMAX		/* 共有メモリの最大セグメントサイズ (バイト) */
#define SHMMIN		/* 共有メモリの最小セグメントサイズ (バイト) */
#define SHMMNI		/* 共有メモリ識別子の最大数 */
#define SHMSEG		/* プロセスごとの共有メモリセグメントの最大数 */
#define SHMALL		/* 共有メモリの最大値 (ページ) */
postmaster がサポートするバッファの数を増やすためには、下記をカーネル設定 ファイルに追加して下さい。 1024のSHMALL値は共有メモリの 4MB を表します。必要に応じて 増やして下さい。
options "SHMALL=4096"
options "SHMMAX=\(SHMALL*PAGE_SIZE\)"

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

$ bpatch -r sysptsize
0x9 = 9
次に、SYSPTSIZEをハードコーディングされた値に 変えて下さい。bpatch 値を使い、更に希望する共有メモリの 4 MB ごとに 1 を追加して下さい。
options "SYSPTSIZE=13"
sysptsizeは起動中は sysctl によって動的に変えることは できません。

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

デフォルトは/sys/sys/sem.h です。


#define SEMMNI  10              /* セマフォ識別子の数 */

#define SEMMNS  60              /* システム内のセマフォの数 */

#define SEMUME  10              /* プロセスごとの取り消し項目の最高数 */

#define SEMMNU  30              /* システム内の取り消し構造体の数 */
設定ファイルの中に必要な値を設定して下さい。例えば下記のようになります。
options "SEMMNI=40"
options "SEMMNS=240"
options "SEMUME=40"
options "SEMMNU=120"

FreeBSD, 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

HP-UX

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

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

Linux

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

$ 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/shmparam.h/usr/src/linux/include/linux/sem.hを見てみて下さい。

SCO OpenServer

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

./configure -y SHMMAX
SHMMAXの新しい値を設定するためには、 valueが使おうとしている新しい値である場所で(バイトで) 下記を実行して下さい。
./configure SHMMAX=value
SHMMAXの設定が終ったら、カーネルをビルドし直して 下さい。
./link_unix
そして再起動して下さい。

Solaris

少なくともバージョン 2.6 では共有メモリセグメントの最大サイズは Postgresには低すぎる設定になっています。 必要な設定は/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 では、共有メモリセグメントの最大サイズ はデフォルト設定で 512 kB です。これは-B 24 -N 12 にはおよそ十分です。現在のSHMMAX値を表示する ためには下記を実行して下さい。

/etc/conf/bin/idtune -g SHMMAX
これは現在の、デフォルトの、最小の、そして最大の、値をバイトで 表示します。SHMMAXの新しい値を設定するためには 下記を、valueが使おうとしている新しい値である 場所で(バイトで)実行して下さい。
/etc/conf/bin/idtune SHMMAX value
SHMMAXの設定が終ったらカーネルのビルドをし直し、
/etc/conf/bin/idbuild -B
再起動して下さい。

3.5.2. リソースの制限

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

default:\
...
        :datasize-cur=256M:\
        :maxproc-cur=256:\
        :openfiles-cur=256:\
...
(-curがソフト制限です。ハード制限を 設定するためには-maxを付けて下さい。)

カーネルは一般的にはいくつかのリソースに、実装に依存するシステム 全体の制限も持っています。

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

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