大きなPostgreSQLのインストレーションになると、オペレーティングシステムのリソースの限界を容易に越えてしまいます(システムによっては出荷時のデフォルトが低すぎるため"大きな"インストレーションの要望にも応えられません)。このような問題に遭遇したことがある場合はこの先を読んでください。
共有メモリとセマフォはひとまとめにして "System V IPC"と呼ばれます(メッセージキューとも一緒ですが、PostgreSQLでは関係ありません)。ほとんどすべての現代のオペレーティングシステムはこれらの機能を提供しますが、特にBSDの痕跡を引きずるシステムのように、すべてがデフォルトで有効にされたり適当なサイズになっているわけではありません( QNXとBeOSにおける移植では、PostgreSQLはこれらの機能の独自の代替実装を提供しています)。
これらの機能の完全な欠落はIllegal system callエラーでpostmaster起動時に表示されます。その場合はカーネルを設定し直すしかありません。PostgreSQLはこれらの機能なしでは動きません。
PostgreSQLがさまざまなIPCリソースのハードリミットを越えるとpostmasterは起動を拒否し、問題に関する限界条件を教え何をすべきかを示すエラーメッセージを残します( Section 3.3.1も参照してください)。関係するカーネルパラメータは別々のシステム上でも統一して名付けられています(Table 3-2で概略がわかります)。しかしこれらを設定するための方法は異なります。以下に、いくつかのプラットフォームへの提案を挙げます。これらの設定を変えるには、しばしばマシンを再起動することが必要になり、カーネルをコンパイルし直す必要がある場合さえあるので注意してください。
Table 3-2. System V IPCパラメータ
名前 | 説明 | 適切な値 |
---|---|---|
SHMMAX | 共有メモリセグメントの最大サイズ(バイト) | 250kバイト + 8.2kバイト * shared_buffers + 14.2kバイト * 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-2の公式を参照してください)。パラメータ SEMMNIはシステム上に同時に存在できるセマフォセットの数の上限を決定します。ですからこのパラメータは少なくとも ceil(max_connections / 16)以上はなくてはいけません。一時的な失敗の回避策としては許可される接続の数を下げることができますが、 "No space left on device"という紛らわしい言葉が関数semget()から表示されます。
場合によってはSEMMAPを少なくともSEMMNSと同じ数だけ増やすことが必要になる場合があるかもしれません。このパラメータはセマフォリソースマップのサイズを定義し、その中では有効なセマフォのそれぞれの隣接したブロックの項目が必要です。セマフォセットが解放されると、解放されたブロックに隣接するすでに存在する項目に追加されるか、もしくは新しいマップの項目の下に登録されます。もしマップが一杯だった場合、解放されたセマフォは(再起動するまで)失われます。したがってセマフォ空間の断片化により時間が経つごとに、有効なセマフォがあるべきよりも少なくなる可能性があります。
1つのセットの中にいくつのセマフォがあるかを決める SEMMSLはPostgreSQLでは少なくとも17はなくてはいけません。
SEMMNU と SEMUMEのような、その他のさまざまな"semaphore undo"に関する設定はPostgreSQLでは問題にする必要がありません。
共有メモリ. デフォルトでは、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"
オプションSYSVSHMとSYSVSEMはカーネルのコンパイル時に有効にする必要があります(デフォルトでは有効になっています)。共有メモリの最大サイズはオプションSHMMAXPGS(ページ数)で決定されます。以下に、さまざまなパラメータの設定方法の例を示します。
options SYSVSHM options SHMMAXPGS=4096 options SHMSEG=256 options SYSVSEM options SEMMNI=256 options SEMMNS=512 options SEMMNU=256 options SEMMAP=256
(実際は NetBSD と OpenBSD では、このキーワードは単数形の option です。)
デフォルトの設定は通常のインストールではほぼ十分です。 HP-UX 10ではSEMMNSの製造デフォルトは128ですが、これは大きなデータベースサイトには低すぎるかもしれません。
IPC パラメータは システム管理マネージャ(SAM)から Kernel Configuration->Configurable Parametersの下で、設定することができます。終わったらCreate A New Kernelを押してください。
共有メモリ制限のデフォルト(SHMMAXと SHMALLの両方とも)は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/shmparam.h と/usr/src/linux/include/linux/sem.hを参照してください。
デフォルトの設定では、セグメントごとに512Kバイトの共有メモリしか許可されていませんが、これは-B 24 -N 12にはほぼ十分です。設定を増やすためには、まず/etc/conf/cf.dディレクトリに移動してください。現在のSHMMAX値をバイトで表示するためには下記を実行してください。
./configure -y SHMMAX
SHMMAXの新しい値を設定するためには、 valueが使おうとしている新しい値(バイトで)で下記を実行してください。
./configure SHMMAX=value
SHMMAXの設定が終わったら、カーネルをビルドし直してください。
./link_unix
そして再起動してください。
少なくともバージョン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 7では、共有メモリセグメントの最大サイズはデフォルト設定で512Kバイトです。これは-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
その後再起動してください。
Unixライクなオペレーティングシステムでは PostgreSQLサーバの操作と関係する可能性のあるさまざまな種類のリソース制限があります。重要なのは、特にユーザごとのプロセス数の制限、プロセスごとのオープンファイルの数、1つのプロセスに対する利用可能なメモリの量です。これらのそれぞれが "ハード"と"ソフト"の2つの制限を持っています。ソフト制限が実際に有効な制限ですが、ユーザによってハード制限まで変えることが可能です。ハード制限はルートユーザーによってのみ変えることができます。システムコールsetrlimitがこれらのパラメータの設定を行います。シェルに組み込まれたコマンド ulimit(Bourne シェル)もしくは limit(csh)は、コマンドラインからリソース制限を制御するために使われます。BSD派生システム上ではファイル /etc/login.confが、さまざまなリソース制限がログイン時にどの値に設定されるかを制御します。詳細は login.conf を参照してください。関連するパラメータはmaxproc、 openfiles、datasizeです。たとえば下記のようになります(-curがソフト制限です。ハード制限を設定するためには-maxを付けてください)。
default:\ ... :datasize-cur=256M:\ :maxproc-cur=256:\ :openfiles-cur=256:\ ...
カーネルは一般的にはいくつかのリソースに対して、実装に依存するシステム全体の制限も持っています。
Linuxでは、 /proc/sys/fs/file-maxが、カーネルが割り当てるオープンファイル数の最大を決定します。この数を変えるためには、そのファイルに別の数を書き込むか、あるいは/etc/sysctl.confに代入値を追加します。プロセスごとのファイルの最大制限はカーネルがコンパイルされたときに固定されます。詳しい情報は /usr/src/linux/Documentation/proc.txtを参照してください。
PostgreSQLサーバはコネクションごとに1つのプロセスを使うので、少なくとも許可された接続の数だけのプロセスに残りのシステムで必要な分を追加したものが必要になります。通常はこれは問題ではありませんが、1つのマシン上でいくつかのサーバを起動している場合は厳しい状況になるかもしれません。
オープンファイルの制限の出荷時のデフォルトは、しばしば大多数のユーザはマシン上でシステムリソースの不正使用をしないという前堤に立った "社会的に友好的な"値を設定してしまいます。もし1つのマシン上で複数のサーバを起動する場合はそれが必要でしょうが、専用サーバではこの制限を上げたいかもしれません。
反対に、個々のプロセスが多数のファイルをオープンすることを許可するシステムもあります。そのようなプロセスが数個以上あれば、システム全体の制限は簡単に越えてしまいます。この発生を検知し、システム全体の制限の変更を望まない場合は、PostgreSQL の max_files_per_process 設定パラメータを設定し、オープンファイルの消費を制限することができます。