From ef2a6b8b833ffcd7686eeb77fd771d4613b0c144 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Sat, 22 Jul 2000 14:49:01 +0000 Subject: [PATCH] Shed some light onto SysV IPC configuration. --- doc/src/sgml/runtime.sgml | 462 +++++++++++++++++++++++++++++++++- src/backend/storage/ipc/ipc.c | 80 ++++-- 2 files changed, 510 insertions(+), 32 deletions(-) diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 78978fdb35..5b85a80c6b 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,5 +1,5 @@ @@ -267,13 +267,13 @@ FATAL: StreamServerPort: bind() failed: Permission denied A message like -IpcMemoryCreate: shmget(5440001, 83918612, 01600) failed: Invalid argument +IpcMemoryCreate: shmget(key=5440001, size=83918612, 01600) failed: Invalid argument FATAL 1: ShmemCreate: cannot create region probably means that your kernel's limit on the size of shared memory areas is smaller than the buffer area that Postgres is trying to create (83918612 bytes in this example). Or it could - mean that you don't have SysV-style shared memory support + mean that you don't have System-V-style shared memory support configured into your kernel at all. As a temporary workaround, you can try starting the postmaster with a smaller-than-normal number of buffers ( switch). You will @@ -286,17 +286,22 @@ FATAL 1: ShmemCreate: cannot create region An error like -IpcSemaphoreCreate: semget(5440026, 16, 0600) failed: No space left on device +IpcSemaphoreCreate: semget(key=5440026, num=16, 01600) failed: No space left on device does not mean that you've run out of disk - space; it means that your kernel's limit on the number of SysV - semaphores is smaller than the number + space; it means that your kernel's limit on the number of System + V semaphores is smaller than the number Postgres wants to create. As above, you may be able to work around the problem by starting the postmaster with a reduced number of backend processes ( switch), but you'll eventually want to increase the kernel limit. + + + Details about configuring System V IPC facilities are given in + . + @@ -1073,6 +1078,445 @@ env PGOPTIONS='--geqo=off' psql + + Managing Kernel Resources + + + A large Postgres installation can quickly hit + various operating system resource limits. (On some systems, the + factory defaults are so low that you don't even need a really + large installation.) If you have encountered this kind of + problem then keep reading. + + + + Shared Memory and Semaphores + + + Shared memory and semaphores are collectively referred to as + System V IPC (together with message queues, which are + not relevant for Postgres). Almost all modern + operating systems provide these features, but not all of them have + them turned on or sufficiently sized by default, especially + systems with BSD heritage. (For the QNX port, + Postgres provides its own replacement + implementation of these facilities.) + + + + The complete lack of these facilities is usually manifested by an + Illegal system call error upon postmaster start. In + that case there's nothing left to do but to reconfigure your + kernel -- Postgres won't work without them. + + + + When Postgres exceeds one of the various hard + limits of the IPC resources then the postmaster will refuse to + start up and should leave a marginally instructive error message + about which problem was encountered and what needs to be done + about it. The relevant kernel parameters have a relatively + consistent nomenclature across systems; gives an overview. The methods to + set them, however, vary; suggestions for some platforms are given + below. Be aware, however, that you will have to reboot your + machine at best, or possibly recompile the kernel, to change these + settings. + + + + + System V IPC parameters</> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</> + <entry>Description</> + <entry>Reasonable values</> + </row> + </thead> + + <tbody> + <row> + <entry><varname>SHMMAX</></> + <entry>Maximum size of shared memory segment (bytes)</> + <entry>512 kB + 8192 * buffers + extra ... infinity</entry> + </row> + + <row> + <entry><varname>SHMMIN</></> + <entry>Minimum size of shared memory segment (bytes)</> + <entry>1 (at most 144)</> + </row> + + <row> + <entry><varname>SHMSEG</></> + <entry>Maximum number of shared memory segments per process</> + <entry>Must be at least 3, but the default is much higher.</> + </row> + + <row> + <entry><varname>SHMMNI</></> + <entry>Maximum number of shared memory segments system-wide</> + <entry>like <varname>SHMSEG</> + room for other applications</> + </row> + + <row> + <entry><varname>SEMMNI</></> + <entry>Maximum number of semaphore identifiers (i.e., sets)</> + <entry>>= ceil(max_connections % 16)</> + </row> + + <row> + <entry><varname>SEMMNS</></> + <entry>Maximum number of semaphores system-wide</> + <entry>number of allowed connections, rounded up to multiple of 16</> + </row> + + <row> + <entry><varname>SEMMSL</></> + <entry>Maximum number of semaphores per set</> + <entry>>= 16</> + </row> + + <row> + <entry><varname>SEMMAP</></> + <entry>Number of entries in semaphore map</> + <entry>see text</> + </row> + + <row> + <entry><varname>SEMVMX</></> + <entry>Maximum value of semaphore</> + <entry>>= 255 (The default is often 32767, don't change unless asked to.)</> + </row> + + </tbody> + </tgroup> + </table> + + + <para> + The most important shared memory parameter is <varname>SHMMAX</>, + the maximum size, in bytes, that a shared memory segment can have. + If you get an error message from <function>shmget</> along the + lines of <errorname>Invalid argument</> then it is possible that + this limit has been exceeded. The size of the required shared + memory segments varies both with the number of requested buffers + (<option>-B</> option) and the number of allowed connections + (<option>-N</> option), although the former is the dominant item. + (You can therefore, as a temporary solution, lower these settings + to get rid of the failures.) As a rough approximation you can + estimate the required segment size as the number of buffers times + the block size (8192 kB by default) plus ample overhead (at least + half a megabyte). Any error message you might get will contain the + size of the failed allocation. (<productname>Postgres</> will + actually use three shared memory segments, but the size of the + other two is negligible for this consideration.) + </para> + + <para> + Less likely to cause problems is the minimum size for shared + memory segments (<varname>SHMMIN</>), which must be at least 144 + for <productname>Postgres</> (it's usually just 1), and the + maximum number of segments system-wide (<varname>SHMMNI</>, as + mentioned, 3 are needed) or per-process (<varname>SHMSEG</>, + ditto). Some systems also have a limit on the total amount of + shared memory in the system; see the platform-specific + instructions below. + </para> + + <para> + <productname>Postgres</> uses one semaphore per allowed connection + (<option>-N</> option), in sets of 16. The maximum number of + semaphores in the system is set by <varname>SEMMNS</>, which + consequently must be at least as high as the connection setting. + The parameter <varname>SEMMNI</> determines the limit on the + number of semaphore sets that can exist on the system at one time. + Hence this parameter must be at least + <literal>ceil(max_connections % 16)</>. Lowering the number of + allowed connections is a temporary workaround for failures, which + are usually confusingly worded <quote><errorname>No space left on + device</></>, from the function <function>semget()</>. + </para> + + <para> + In some cases it might also turn out to be necessary to increase + <varname>SEMMAP</> to be at least on the order of + <varname>SEMMNS</>. This parameter defines the size of the + semaphore resource map, in which each contiguous block of available + semaphores needs an entry. When a semaphore set is freed it is + either added to an existing entry that is adjacent to the freed + block or it is registered under a new map entry. If the map is + full, the freed semaphores gets lost (until reboot). Fragmentation + of the semaphore space could therefore over time lead to less + available semaphores than there should be. + </para> + + <para> + The <varname>SEMMSL</> parameter, which determines how many + semaphores can be in a set, must be at least 16 for + <productname>Postgres</>. + </para> + + <para> + Various settings related to <quote>semaphore undo</>, such as + <varname>SEMMNU</> and <varname>SEMUME</>, are not of relevance + with <productname>Postgres</>. + </para> + + + <para> + <variablelist> + + <varlistentry> + <term>BSD/OS</> + <listitem> + <formalpara> + <title>Shared Memory</> + <para> + By default, only 4 MB of shared memory is supported. Keep in + mind that shared memory is not pageable; it is locked in RAM. + To increase the number of buffers supported by the + postmaster, increase <varname>SHMMAXPGS</> by 1024 for every + additional 4 MB of shared memory: +<programlisting> +/sys/sys/shm.h:69:#define SHMMAXPGS 1024 /* max hardware pages... */ +</programlisting> + The default setting of 1024 is for a maximum of 4 MB of shared + memory. + </para> + </formalpara> + + <para> + For those running 4.1 or later, just recompile the kernel and + reboot. For those running earlier releases, use + <application>bpatch</> to find the <varname>sysptsize</> value + for the current kernel. This is computed dynamically at + bootup. +<screen> +$ <userinput>bpatch -r sysptsize</> +<computeroutput>0x9 = 9</> +</screen> + Next, change <varname>SYSPTSIZE</> to a hard-coded value. Use + the bpatch value, plus add 1 for every additional 4 MB of + shared memory you desire. +<programlisting> +/sys/i386/i386/i386_param.c:28:#define SYSPTSIZE 0 /* dynamically... */ +</programlisting> + <varname>sysptsize</> can not be changed by sysctl on the fly. + </para> + + <formalpara> + <title>Semaphores</> + <para> + You may need to increase the number of semaphores. By + default, <productname>Postgres</> allocates 32 semaphores, + one for each backend connection. This is just over half the + default system total of 60. + </para> + </formalpara> + + <para> + The defaults are in <filename>/sys/sys/sem.h</>: +<programlisting> +/* Configuration parameters */ +#ifndef SEMMNI +#define SEMMNI 10 /* # of semaphore identifiers */ +#endif +#ifndef SEMMNS +#define SEMMNS 60 /* # of semaphores in system */ +#endif +#ifndef SEMUME +#define SEMUME 10 /* max # of undo entries per process */ +#endif +#ifndef SEMMNU +#define SEMMNU 30 /* # of undo structures in system */ +#endif +</programlisting> + Set the values you want in your kernel config file, e.g.: +<programlisting> +options "SEMMNI=40" +options "SEMMNS=240" +options "SEMUME=40" +options "SEMMNU=120" +</programlisting> + </para> + </listitem> + </varlistentry> + + + <varlistentry> + <term>FreeBSD</> + <listitem> + <para> + The options <varname>SYSVSHM</> and <varname>SYSVSEM</> need + to be enabled when the kernel is compiled. (They are by + default.) The maximum size of shared memory is determined by + the option <varname>SHMMAXPGS</> (in pages). The following + shows an example on how to set the various parameters: +<programlisting> +options SYSVSHM +options SHMMAXPGS=4096 +options SHMSEG=256 + +options SYSVSEM +options SEMMNI=256 +options SEMMNS=512 +options SEMMNU=256 +options SEMMAP=256 +</programlisting> + </para> + </listitem> + </varlistentry> + + + <varlistentry> + <term>HPUX</> + <listitem> + <para> + The default settings tend to suffice for normal installations. + On <productname>HPUX</> 10, the factory default for + <varname>SEMMNS</> is 128, which might be too low for larger + database sites. + </para> + <para> + IPC parameters can be set in the <application>System + Administration Manager</> (<acronym>SAM</>) under + <menuchoice><guimenu>Kernel + Configuration</><guimenuitem>Configurable Parameters</></>. + Hit <guibutton>Create A New Kernel</> when you're done. + </para> + </listitem> + </varlistentry> + + + <varlistentry> + <term>Linux</> + <listitem> + <para> + System V IPC is enabled by default and sufficiently sized for + most uses. The relevant parameters are in + <filename>/usr/src/linux/include/asm-<replaceable>xxx</>/shmparam.h</> + and <filename>/usr/src/linux/include/linux/sem.h</>. Be sure + to do <command>make dep</> before rebuilding the kernel. + </para> + </listitem> + </varlistentry> + + + <varlistentry> + <term>SCO OpenServer</> + <listitem> + <para> + In the default configuration, only 512 kB of shared memory per + segment is allowed, which is about enough for <option>-B 24 -N + 12</>. To increase the setting, first change the directory to + <filename>/etc/conf/cf.d</>. To display the current value of + <varname>SHMMAX</>, in bytes, run +<programlisting> +./configure -y SHMMAX +</programlisting> + To set a new value for <varname>SHMMAX</>, run: +<programlisting> +./configure SHMMAX=<replaceable>value</> +</programlisting> + where <replaceable>value</> is the new value you want to use + (in bytes). After setting <varname>SHMMAX</>, rebuild the kernel +<programlisting> +./link_unix +</programlisting> + and reboot. + </para> + </listitem> + </varlistentry> + + + <varlistentry> + <term>Solaris</> + <listitem> + <para> + At least in version 2.6, the maximum size of a shared memory + segment is set too low for <productname>Postgres</>. The + relevant settings can be changed in <filename>/etc/system</>, + for example: +<programlisting> +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 +</programlisting> + You need to reboot to make the changes effective. + </para> + + <para> + See also <ulink + url="http://www.sunworld.com/swol-09-1997/swol-09-insidesolaris.html">http://www.sunworld.com/swol-09-1997/swol-09-insidesolaris.html</> + for information on shared memory under + <productname>Solaris</>. + </para> + </listitem> + </varlistentry> + + + <varlistentry> + <term>UnixWare</> + <listitem> + <para> + On <productname>UnixWare</> 7, the maximum size for shared + memory segments is 512 kB in the default configuration. This + is enough for about <option>-B 24 -N 12</>. To display the + current value of <varname>SHMMAX</>, run +<programlisting> +/etc/conf/bin/idtune -g SHMMAX +</programlisting> + which displays the current, default, minimum, and maximum + values, in bytes. To set a new value for <varname>SHMMAX</>, + run: +<programlisting> +/etc/conf/bin/idtune SHMMAX <replaceable>value</> +</programlisting> + where <replaceable>value</> is the new value you want to use + (in bytes). After setting <varname>SHMMAX</>, rebuild the + kernel +<programlisting> +/etc/conf/bin/idbuild -B +</programlisting> + and reboot. + </para> + </listitem> + </varlistentry> + + </variablelist> + + <note> + <para> + If your platform is not listed here, please consider + contributing some information. + </para> + </note> + </para> + </sect2> + +<!-- + Other fun things to write about one day: + * number of processes per user and system-wide (soft/hard limit) + * open files/inodes per user and system-wide (soft/hard limit) + (Think about this both ways: Increasing it to allow Postgres to + open more files, and decreasing it to prevent Postgres from taking + up all file descriptors.) + * stack and data segment size, plain-old memory limit +--> + + </sect1> + + <sect1 id="locale"> <title>Locale Support @@ -1142,8 +1586,9 @@ postmaster -B 1024 -S -D/usr/local/pgsql/data/ -o '-Fe' and if locale is broken perl -v will complain something like: -8:17[mira]:~/WWW/postgres>setenv LC_CTYPE not_exist -8:18[mira]:~/WWW/postgres>perl -v +$ export LC_CTYPE='not_exist' +$ perl -v + perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LC_ALL = (unset), @@ -1151,6 +1596,7 @@ LC_CTYPE = "not_exist", LANG = (unset) are supported and installed on your system. perl: warning: Falling back to the standard locale ("C"). + diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c index 8e4a29041e..942e72cac0 100644 --- a/src/backend/storage/ipc/ipc.c +++ b/src/backend/storage/ipc/ipc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.48 2000/05/31 00:28:29 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.49 2000/07/22 14:49:01 petere Exp $ * * NOTES * @@ -54,7 +54,6 @@ bool proc_exit_inprogress = false; static int UsePrivateMemory = 0; static void IpcMemoryDetach(int status, char *shmaddr); -static void IpcConfigTip(void); /* ---------------------------------------------------------------- * exit() handling stuff @@ -241,7 +240,9 @@ IPCPrivateSemaphoreKill(int status, union semun semun; semun.val = 0; /* unused */ - semctl(semId, 0, IPC_RMID, semun); + if (semctl(semId, 0, IPC_RMID, semun) == -1) + elog(NOTICE, "IPCPrivateSemaphoreKill: semctl(%d, 0, IPC_RMID, ...) failed: %s", + semId, strerror(errno)); } @@ -261,8 +262,8 @@ IPCPrivateMemoryKill(int status, { if (shmctl(shmId, IPC_RMID, (struct shmid_ds *) NULL) < 0) { - elog(NOTICE, "IPCPrivateMemoryKill: shmctl(%d, %d, 0) failed: %m", - shmId, IPC_RMID); + elog(NOTICE, "IPCPrivateMemoryKill: shmctl(id=%d, IPC_RMID, NULL) failed: %m", + shmId); } } } @@ -307,10 +308,19 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey, if (semId < 0) { - fprintf(stderr, "IpcSemaphoreCreate: semget(%d, %d, 0%o) failed: %s\n", + fprintf(stderr, "IpcSemaphoreCreate: semget(key=%d, num=%d, 0%o) failed: %s\n", semKey, semNum, (unsigned)(permission|IPC_CREAT), strerror(errno)); - IpcConfigTip(); + + if (errno == ENOSPC) + fprintf(stderr, + "\nThis error does *not* mean that you have run out of disk space.\n\n" + "It occurs either because system limit for the maximum number of\n" + "semaphore sets (SEMMNI), or the system wide maximum number of\n" + "semaphores (SEMMNS), would be exceeded. You need to raise the\n" + "respective kernel parameter. Look into the PostgreSQL documentation\n" + "for details.\n\n"); + return (-1); } for (i = 0; i < semNum; i++) @@ -319,10 +329,16 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey, errStatus = semctl(semId, 0, SETALL, semun); if (errStatus == -1) { - fprintf(stderr, "IpcSemaphoreCreate: semctl(id=%d) failed: %s\n", + fprintf(stderr, "IpcSemaphoreCreate: semctl(id=%d, 0, SETALL, ...) failed: %s\n", semId, strerror(errno)); + + if (errno == ERANGE) + fprintf(stderr, + "You possibly need to raise your kernel's SEMVMX value to be at least\n" + "%d. Look into the PostgreSQL documentation for details.\n", + semStartValue); + semctl(semId, 0, IPC_RMID, semun); - IpcConfigTip(); return (-1); } @@ -516,9 +532,35 @@ IpcMemoryCreate(IpcMemoryKey memKey, uint32 size, int permission) if (shmid < 0) { - fprintf(stderr, "IpcMemoryCreate: shmget(%d, %d, 0%o) failed: %s\n", - memKey, size, (unsigned)(IPC_CREAT|permission), strerror(errno)); - IpcConfigTip(); + fprintf(stderr, "IpcMemoryCreate: shmget(key=%d, size=%d, 0%o) failed: %s\n", + (int)memKey, size, (unsigned)(IPC_CREAT|permission), + strerror(errno)); + + if (errno == EINVAL) + fprintf(stderr, + "\nThis error can be caused by one of three things:\n\n" + "1. The maximum size for shared memory segments on your system was\n" + " exceeded. You need to raise the SHMMAX parameter in your kernel\n" + " to be at least %d bytes.\n\n" + "2. The requested shared memory segment was too small for your system.\n" + " You need to lower the SHMMIN parameter in your kernel.\n\n" + "3. The requested shared memory segment already exists but is of the\n" + " wrong size. This is most likely the case if an old version of\n" + " PostgreSQL crashed and didn't clean up. The `ipcclean' utility\n" + " can be used to remedy this.\n\n" + "The PostgreSQL Administrator's Guide contains more information about\n" + "shared memory configuration.\n\n", + size); + + else if (errno == ENOSPC) + fprintf(stderr, + "\nThis error does *not* mean that you have run out of disk space.\n\n" + "It occurs either if all available shared memory ids have been taken,\n" + "in which case you need to raise the SHMMNI parameter in your kernel,\n" + "or because the system's overall limit for shared memory has been\n" + "reached. The PostgreSQL Administrator's Guide contains more\n" + "information about shared memory configuration.\n\n"); + return IpcMemCreationFailed; } @@ -541,7 +583,7 @@ IpcMemoryIdGet(IpcMemoryKey memKey, uint32 size) if (shmid < 0) { - fprintf(stderr, "IpcMemoryIdGet: shmget(%d, %d, 0) failed: %s\n", + fprintf(stderr, "IpcMemoryIdGet: shmget(key=%d, size=%d, 0) failed: %s\n", memKey, size, strerror(errno)); return IpcMemIdGetFailed; } @@ -558,7 +600,7 @@ static void IpcMemoryDetach(int status, char *shmaddr) { if (shmdt(shmaddr) < 0) - elog(NOTICE, "IpcMemoryDetach: shmdt(0x%p): %m", shmaddr); + elog(NOTICE, "IpcMemoryDetach: shmdt(0x%p) failed: %m", shmaddr); } /****************************************************************************/ @@ -694,13 +736,3 @@ LockIsFree(int lockid) #endif #endif /* HAS_TEST_AND_SET */ - -static void -IpcConfigTip(void) -{ - fprintf(stderr, "This type of error is usually caused by an improper\n"); - fprintf(stderr, "shared memory or System V IPC semaphore configuration.\n"); - fprintf(stderr, "For more information, see the FAQ and platform-specific\n"); - fprintf(stderr, "FAQ's in the source directory pgsql/doc or on our\n"); - fprintf(stderr, "web site at http://www.postgresql.org.\n"); -} -- GitLab