16.4. Gérer les ressources du noyau

Une installation importante de PostgreSQL™ peut rapidement épuiser les limites des ressources du système d'exploitation. (Sur certains systèmes, les valeurs par défaut sont trop basses que vous n'avez même pas besoin d'une installation « importante ».) si vous avez rencontré ce type de problème, continuez votre lecture.

16.4.1. Mémoire partagée et sémaphore

La mémoire partagée et les sémaphores sont nommés collectivement « ipc system v » (ensemble avec les queues de messages, qui n'ont pas d'importance pour PostgreSQL™). pratiquement, tous les systèmes d'exploitation modernes fournissent ces fonctionnalités mais, parmi elles, toutes ne sont pas activées ou dimensionnées suffisamment par défaut, spécialement les systèmes ayant l'héritage BSD (pour le port windows, PostgreSQL™ fournit sa propre implémentation de remplacement de ces fonctionnalités).

Le manque complet de fonctionnalités est généralement manifesté par une erreur illegal system call au lancement du serveur. dans ce cas, il n'y a rien à faire à part reconfigurer votre noyau. PostgreSQL™ ne fonctionnera pas sans.

Quand PostgreSQL™ dépasse une des nombreuses limites ipc, le serveur refusera de s'exécuter et lèvera un message d'erreur instructif décrivant le problème rencontré et que faire avec (voir aussi la Section 16.3.1, « Échecs de lancement »). les paramètres adéquats du noyau sont nommés de façon cohérente parmi les différents systèmes ; le Tableau 16.1, « Paramètres system v ipc » donne un aperçu. Néanmoins, les méthodes pour les obtenir varient. Les suggestions pour quelques plateformes sont données ci-dessous. Attention, il est souvent nécessaire de redémarrer votre machine, voire même de recompiler le noyau, pour changer ces paramétrages.

Tableau 16.1. Paramètres system v ipc

Nom Description Valeurs raisonnables
shmmax taille maximum du segment de mémoire partagée (octets) au moins plusieurs mo (voir texte)
shmmin taille minimum du segment de mémoire partagée (octets) 1
shmall total de la mémoire partagée disponible (octets ou pages) si octets, identique à shmmax ; si pages, ceil(shmmax/page_size)
shmseg nombre maximum de segments de mémoire partagée par processus seul un segment est nécessaire mais la valeur par défaut est bien plus importante
shmmni nombre maximum de segments de mémoire partagée pour tout le système comme shmseg plus la place pour les autres applications
semmni nombre maximum d'identifiants de sémaphores (c'est-à-dire d'ensembles) au moins ceil(max_connections / 16)
semmns nombre maximum de sémaphores répartis dans le système ceil(max_connections / 16) * 17 plus la place pour les autres applications
semmsl nombre maximum de sémaphores par ensemble au moins 17
semmap nombre d'entrées dans la carte des sémaphores voir le texte
semvmx valeur maximum d'un sémaphore au moins 1000 (vaut souvent par défaut 32767, ne pas changer sauf si vous êtes forcé.)

le paramètre de mémoire partagé le plus important est shmmax, la taille maximum, en octets, d'un segment de mémoire partagée. Si vous obtenez un message d'erreur à partir de shmget comme invalid argument, il est possible que cette limite soit dépassée. La taille du segment de mémoire partagée requis dépend de plusieurs paramètres de configuration de PostgreSQL™, comme indiqué dans le Tableau 16.2, « Paramètres de configuration affectant l'utilisation de la mémoire partagée par PostgreSQL™ ». temporairement, vous pouvez baisser certains de ces paramètres pour éviter un échec. Comme approximation brute, vous pouvez estimer la taille du segment requis à 500 Ko auquel vous ajoutez les tailles variables affichées dans la table (tout message d'erreur obtenu incluera la taille exacte utilisée dans la requête d'allocation qui a échoué). Alors qu'il est possible d'obtenir de PostgreSQL™ qu'il fonctionne avec un shmmax de 1 Mo, vous devez disposer d'au moins 4 Mo pour obtenir des performances acceptables. Les paramètrages désirables sont plutôt de l'ordre de dizaines de Mo.

Certains systèmes ont aussi une limite sur le nombre total de mémoire partagée dans le système (shmall). assurez-vous que cela soit suffisamment important pour PostgreSQL™ et quelque autres applications utilisant des segments de mémoire partagée (attention : shmall est mesuré en pages plutôt qu'en octets sur beaucoup de systèmes).

La taille minimum des segments de mémoire partagée (shmmin) est moins sensible aux problèmes. Elle devrait être au plus à environ 500 Ko pour PostgreSQL™ (il est habituellement à 1). le nombre maximum de segments au travers du système (shmmni) ou par processus (shmseg) a peu de chances de causer un problème sauf s'ils sont configurés à zéro sur votre système.

PostgreSQL™ utilise un sémaphore par connexion autorisée (max_connections), par ensemble de 16. chacun de ces ensembles contiendra aussi un 17è sémaphore qui contient un « nombre magique » pour détecter la collision avec des ensembles de sémaphore utilisés par les autres applications. Le nombre maximum de sémaphores dans le système est initialisé par semmns, qui en conséquence doit être au moins aussi haut que max_connections plus un extra de chacune des 16 connexions autorisées (voir la formule dans le Tableau 16.1, « Paramètres system v ipc »). Le paramètre semmni détermine la limite sur le nombre d'ensembles de sémaphores qui peuvent exister sur le système à un instant précis. Donc, ce paramètre doit être au moins égal à ceil(max_connections / 16). baisser le nombre de connexions autorisées est un contournement temporaire pour les échecs qui sont habituellement indiqués par le message no space left on device, à partir de la fonction semget.

Dans certains cas, il pourrait être nécessaire d'augmenter semmap pour être au moins dans l'ordre de semmns. ce paramètre définit la taille de la carte de ressources de sémaphores, dans laquelle chaque bloc contigü de sémaphores disponibles ont besoin d'une entrée. Lorsqu'un ensemble de sémaphores est libéré ou qu'il est enregistré sous une nouvelle entrée de carte. Si la carte est pleine, les sémaphores libérés sont perdus (jusqu'au redémarrage). La fragmentation de l'espace des sémaphores pourrait amener dans le temps à moins de sémaphores disponibles.

La paramètre semmsl, qui détermine le nombre de sémaphores dans un ensemble, pourrait valoir au moins 17 pour PostgreSQL™.

D'autres paramètres en relation avec l'« annulation de sémaphores », tels que semmnu et semume, ne concernent pas PostgreSQL™.

bsd/os

Mémoire partagée.  Par défaut, seulement 4 Mo de mémoire partagée est supportée. Gardez en tête que la mémoire partagée n'est pas paginable ; elle est verrouillée en RAM. Pour accroître la mémoire partagée supportée par votre système, ajoutez ce qui suit à la configuration de votre noyau. Une valeur de 1024 pour shmall représente 4 mo de mémoire partagée. Pour argumenter la mémoire partagée supportée par votre système, ajoutez quelque chose comme ceci à votre configuration du noyau :

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

shmall est mesuré en pages de 4 Ko, donc une valeur de 1024 représente 4 Mo de mémoire partagée. Du coup, la configuration ci-dessus augmente l'aire de mémoire partagée à 32 Mo. Pour ceux utilisant une version 4.3 ou ultérieure, vous aurez probablement besoin d'augmenter kernel_virtual_mb au-dessus de la valeur par défaut, 248. une fois tous les changements effectués, recompilez le noyau et redémarrez.

Pour ceux utilisant une version 4.0 ou antérieures, utilisez bpatch pour connaître la valeur sysptsize dans le noyau actuel. Elle est calculée dynamiquement au démarrage.

$ bpatch -r sysptsize
0x9 = 9

Ensuite, ajoutez sysptsize comme valeur codée en dur dans le fichier de configuration du noyau. Augmentez la valeur que vous trouvez en utilisant bpatch. ajoutez 1 pour chaque 4 Mo supplémentaire de mémoire partagée que vous souhaitez.

options "SYSPTSIZE=16"

sysptsize ne peut pas être modifié avec sysctl.

Sémaphores.  Vous voudrez probablement aussi augmenter le nombre de sémaphores ; la somme totale par défaut du système (60) n'autorisera seulement que 50 connexions PostgreSQL™. initialisez les valeurs que vous souhaitez dans le fichier de configuration du noyau :

options "SEMMNI=40"
options "SEMMNS=240"
freebsd

Les paramètres par défaut sont seulement acceptables pour de petites installations (par exemple, la valeur par défaut de shmmax est de 32 mo). les modifications se font via les interfaces sysctl ou loader. les paramètres suivants peuvent être configurés en utilisant sysctl :

$ sysctl -w kern.ipc.shmall=32768
$ sysctl -w kern.ipc.shmmax=134217728
$ sysctl -w kern.ipc.semmap=256

Pour que ces paramètres persistent après les redémarrages, modifiez /etc/sysctl.conf.

Les paramètres restant, concernant les sémaphores, sont en lecture seule en ce qui concerne sysctl mais peuvent être modifiés avant le redémarrage en utilisant l'invite loader :

(loader) set kern.ipc.semmni=256
(loader) set kern.ipc.semmns=512
(loader) set kern.ipc.semmnu=256

De façon similaire, ils peuvent être sauvegardés entre les redémarrages dans /boot/loader.conf.

Vous pourriez aussi vouloir configurer votre noyau pour verrouiller la mémoire partagée en RAM et l'empêcher d'être envoyé dans la swap. Ceci s'accomplit en utilisant le paramètre kern.ipc.shm_use_phys de sysctl.

En cas d'exécution dans une cage FreeBSD en activant security.jail.sysvipc_allowed de sysctl, les postmaster exécutés dans différentes cages devront être exécutés par différents utilisateurs du système d'exploitation. Ceci améliore la sécurité car cela empêche les utilisateurs non root d'interférer avec la mémoire partagée ou les sémaphores d'une cage différente et cela permet au code de nettoyage des IPC PostgreSQL de fonctionner correctement (dans FreeBSD 6.0 et ultérieurs, le code de nettoyage IPC ne détecte pas proprement les processus des autres cages, empêchant les postmaster en cours d'exécution d'utiliser le même port dans différentes cages).

Les freebsd, avant la 4.0, fonctionnent comme netbsd et OpenBSD (voir ci-dessous).

netbsd, openbsd

Les options sysvshm et sysvsem doivent être activées à la compilation du noyau (ils le sont par défaut). La taille maximum de mémoire partagée est déterminée par l'option shmmaxpgs (en pages). ce qui suit montre un exemple de l'initialisation des différents paramètres (OpenBSD utilise option à la place) :

options         SYSVSHM
options         SHMMAXPGS=4096
options         SHMSEG=256

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

Vous pourriez aussi vouloir configurer votre noyau pour verrouiller la mémoire partagée en RAM et l'empêcher d'être paginée en swap. Ceci se fait en utilisant le paramètre kern.ipc.shm_use_phys de sysctl.

hp-ux

Les paramètres par défaut tendent à suffire pour des installations normales. Sur hp-ux™ 10, la valeur par défaut de semmns est 128, qui pourrait être trop basse pour de gros sites de bases de données.

Les paramètres ipc peuvent être initialisés dans system administration manager (sam) sous kernel configurationconfigurable Parameters. allez sur create a new kernel une fois terminée.

linux

Les paramètres par défaut sont seulement convenables pour de petites installations (la taille du segment max par défaut est de 32 Mo). Néanmoins, les paramètres restants sont assez généreusement configurés et ne requièrent pas habituellement de modifications. La taille du segment max peut être modifiée via l'interface sysctl. Par exemple, pour autoriser 128 Mo et pour configurer explicitement la taille de la mémoire partagée à 2097152 pages (la valeur par défaut) :

$ sysctl -w kernel.shmmax=134217728
$ sysctl -w kernel.shmall=2097152

De plus, ces paramètrages peuvent être conservés entre les redémarrages dans /etc/sysctl.conf.

Les anciennes distributions pourraient ne pas disposer du programme sysctl mais des modifications équivalentes peuvent se faire en manipulant le système de fichiers /proc :

$ echo 134217728 >/proc/sys/kernel/shmmax
$ echo 2097152 >/proc/sys/kernel/shmall
macos x

Avec OS X 10.2 et antérieures, éditez le fichier /system/library/startupitems/systemtuning/systemtuning et modifiez les valeurs avec les commandes suivantes :

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

Avec OS X 10.3 et les versions suivantes, ces commandes ont été déplacées dans /etc/rc et doivent être éditées là-bas. Notez que /etc/rc est habituellement surchargé par les mises à jour d'OS X (comme celle de 10.3.6 à 10.3.7) donc vous devez vous attendre à avoir à refaire votre édition après chaque mise à jour.

Sous OS X 10.3.9 et les versions ultérieures, au lieu de modifier /etc/rc, vous pouvez créer un fichier nommé /etc/sysctl.conf contenant des affectations de variables comme

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

Cette méthode est préférée à la modification de /etc/rc car vos modifications seront préservées y compris après les mises à jour du système. Notez que les cinq paramètres de mémoire partagée doivent être configurés dans /etc/sysctl.conf, sinon les valeurs seront ignorées.

Attention au fait que les versions récentes d'OS X ignorent les tentatives de configuration de SHMMAX à une valeur qui n'est pas un multiple exact de 4096.

SHMALL est mesuré en page de 4 Ko sur cette plateforme.

Dans toutes les versions d'OS X, vous aurez besoin de redémarrer pour que les modifications de mémoire partagée soient prises en considération.

sco openserver

Dans la configuration par défaut, seuls 512 Ko de mémoire partagée par segment est autorisé. Pour augmenter ce paramétrage, allez tout d'abord dans le répertoire /etc/conf/cf.d. pour afficher la valeur courante de shmmax, lancez

./configure -y SHMMAX

Pour configurer une nouvelle valeur de shmmax, lancez

./configure SHMMAX=valeur

value est la nouvelle valeur que vous voulez utiliser (en octets). Après avoir configuré shmmax, reconstruisez le noyau :

./link_unix

et redémarrez.

aix

Au moins à partir de la version 5.1, il ne devrait plus être nécessaire de faire une configuration spéciale pour tel paramètre comme shmmax car il apparaît qu'il est configuré pour autoriser l'utilisation de toute la mémoire comme mémoire partagée. C'est la sorte de configuration utilisée habituellement pour les autres bases de données comme db/2.

Néanmoins, cela pourrait être nécessaire pour modifier l'information globale ulimit dans /etc/security/limits car les limites dures par défaut pour les tailles de fichiers (fsize) et les nombres de fichiers (nofiles) pourraient être trop bas.

solaris

Au moins dans la version 2.6, la taille maximum par défaut des segments de mémoire partagée est trop basse pour PostgreSQL™. le paramétrage adéquat peut être modifié dans /etc/system, par exemple :

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

Vous avez besoin de redémarrer pour que les modifications prennent effet.

Voir aussi http://sunsite.uakom.sk/sunworldonline/swol-09-1997/swol-09-insidesolaris.html pour des informations sur la mémoire partagée sous solaris™.

unixware

Avec unixware™ 7, la taille maximum des segments de mémoire partagée est de 512 Ko dans la configuration par défaut. Pour afficher la valeur courante de shmmax, lancez

/etc/conf/bin/idtune -g SHMMAX

qui affiche la valeur courante, par défaut, minimum et maximum. Pour configurer une nouvelle valeur de shmmax, lancez

/etc/conf/bin/idtune SHMMAX valeur

valeur est la nouvelle valeur que vous voulez utiliser (en octets). Après avoir initialisé shmmax, reconstruisez le noyau :

/etc/conf/bin/idbuild -B

et relancez.

Tableau 16.2. Paramètres de configuration affectant l'utilisation de la mémoire partagée par PostgreSQL

Nom Multiplicateur approximatif (octets par incrément)
max_connections 400 + 270 * max_locks_per_transaction
max_prepared_transactions 600 + 270 * max_locks_per_transaction
shared_buffers 8300 (en supposant 8 ko par BLCKSZ)
wal_buffers 8200 (en supposant 8 ko par XLOG_BLCKSZ)
max_fsm_relations 70
max_fsm_pages 6

16.4.2. Limites de ressources

Les systèmes d'exploitation style Unix renforcent différents types de limites de ressources qui pourraient interférer avec les opérations de votre serveur PostgreSQL™. les limites sur le nombre de processus par utilisateur, le nombre de fichiers ouverts par un processus et la taille mémoire disponible pour chaque processus sont d'une grande importance. Chacun d'entre elles ont une limite « dure » et une limite « souple ». la limite souple est réellement ce qui compte mais cela pourrait être changé par l'utilisateur jusqu'à la limite dure. La limite dure pourrait seulement être modifiée par l'utilisateur root. L'appel système setrlimit est responsable de l'initialisation de ces paramètres. La commande interne du shell ulimit (shells Bourne) ou limit (csh) est utilisé pour contrôler les limites de ressource à partir de la ligne de commande. Sur les systèmes dérivés BSD, le fichier /etc/login.conf contrôle les différentes limites de ressource initialisées à la connexion. Voir la documentation du système d'exploitation pour les détails. Les paramètres en question sont maxproc, openfiles et datasize. par exemple :

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

(-cur est la limite douce. ajoutez -max pour configurer la limite dure.)

Les noyaux peuvent aussi avoir des limites sur le système complet pour certaines ressources.

  • Sur linux™, /proc/sys/fs/file-max détermine le nombre maximum de fichiers ouverts que le noyau supportera. Ce nombre est modifiable en écrivant un autre nombre dans le fichier ou en ajoutant une affectation dans /etc/sysctl.conf. la limite des fichiers par processus est fixée lors de la compilation du noyau ; voir /usr/src/linux/documentation/proc.txt pour plus d'informations.

Le serveur PostgreSQL™ utilise un processus par connexion de façon à ce que vous puissiez fournir au moins autant de processus que de connexions autorisées, en plus de ce dont vous avez besoin pour le reste de votre système. Ceci n'est habituellement pas un problème mais si vous exécutez plusieurs serveurs sur une seule machine, cela pourrait devenir étroit.

La limite par défaut des fichiers ouverts est souvent initialisée pour être « amicalement sociale », pour permettre à de nombreux utilisateurs de coexister sur une machine sans utiliser une fraction inappropriée des ressources du système. Si vous lancez un grand nombre de serveurs sur une machine, cela pourrait être quelque chose que vous souhaitez mais sur les serveurs dédiés, vous pourriez vouloir augmenter cette limite.

D'un autre côté, certains systèmes autorisent l'ouverture d'un grand nombre de fichiers à des processus individuels ; si un plus grand nombre le font, alors les limites du système peuvent facilement être dépassées. Si vous rencontrez ce cas et que vous ne voulez pas modifier la limite du système, vous pouvez initialiser le paramètre de configuration max_files_per_process de PostgreSQL™ pour limiter la consommation de fichiers ouverts.

16.4.3. Linux memory overcommit

Dans Linux 2.4 et suivants, le comportement par défaut de la mémoire virtuelle n'est pas optimal pour PostgreSQL™. Du fait de l'implémentation du « memory overcommit » par le noyau, celui-ci peut arrêter le serveur PostgreSQL™ (le processus serveur maître, « postmaster ») si les demandes de mémoire d'un autre processus provoque un manque de mémoire virtuelle au niveau du système.

Si cela se produit, un message du noyau qui ressemble à ceci (consulter la documentation et la configuration du système pour savoir où chercher un tel message) :

Out of Memory: Killed process 12345 (postgres)

peut survenir. Ceci indique que le processus postgres a été terminé à cause d'un problème de mémoire. Bien que les connexions en cours continuent de fonctionner normalement, aucune nouvelle connexion n'est acceptée. Pour revenir à un état normal, PostgreSQL™ doit être relancé.

Une façon d'éviter ce problème revient à lancer PostgreSQL™ sur une machine où vous pouvez vous assurer que les autres processus ne mettront pas la machine en manque de mémoire.

Sur Linux 2.6 et ultérieure, une meilleure solution est de modifier le comportement du noyau de façon à ce qu'il n'« overcommit » pas la mémoire. Ceci se fait en sélectionnant le mode overcommit strict via sysctl :

sysctl -w vm.overcommit_memory=2

ou en plaçant une entrée équivalente dans /etc/sysctl.conf. Vous pourriez souhaiter modifier le paramétrage relatif vm.overcommit_ratio. pour les détails, voir la documentation du noyau (documentation/vm/overcommit-accounting).

Quelques noyaux 2.4 de vendeurs ont des pré-versions de l'overcommit du 2.6. Néanmoins, configurer vm.overcommit_memory à 2 sur un noyau qui n'a pas le code correspondant rendra les choses pires qu'elles n'étaient. Il est recommandé d'inspecter le code source du noyau (voir la fonction vm_enough_memory dans le fichier mm/mmap.c) pour vérifier ce qui est supporté dans votre copie avant d'essayer ceci avec une installation 2.4. La présence du fichier de documentation overcommit-accounting ne devrait pas être pris comme une preuve de la présence de cette fonctionnalité. En cas de doute, consultez un expert du noyau ou le vendeur de votre noyau.