Documentation PostgreSQL 15.15 » Administration du serveur » Configuration du serveur et mise en place » Gérer les ressources du noyau

Précédent | Niveau supérieur | Suivant
19.3. Lancer le serveur de bases de données | Sommaire | 19.5. Arrêter le serveur

## 19.4. Gérer les ressources du noyau

PostgreSQL peut quelque fois dépasser les limites des ressources du système d'exploitation, tout spécialement quand plusieurs copies du serveur s'exécutent sur le même système, ou sur des très grosses installations. Cette section explique les ressources du noyau utilisées par PostgreSQL et les étapes à suivre pour résoudre les problèmes liés à la consommation des ressources du noyau.

### 19.4.1. Mémoire partagée et sémaphore

PostgreSQL a besoin que le système d'exploitation fournisse des fonctionnalités de communication inter-processus (IPC), en particulier de la mémoire partagée et des sémaphores. Les systèmes dérivés d'Unix fournissent « System V » IPC, « POSIX » IPC ou les deux. Windows qui fournit sa propre implémentation de ces fonctionnalités ne sera pas approfondi ici.

Par défaut, PostgreSQL alloue une très petite quantité de mémoire partagée System V, ainsi qu'une quantité bien plus importante de mémoire partagée anonyme `mmap`. Autre possibilité : utiliser un seul gros bloc de mémoire partagée System V (voir shared_memory_type). De plus, un nombre important de sémaphores de style System V ou POSIX sont créés au démarrage du serveur. Actuellement, les sémaphores POSIX sont utilisés sur les systèmes Linux et FreeBSD, alors que les autres plateformes utilisent les sémaphores System V.

Les fonctionnalités System V IPC sont habituellement restreintes par les limites d'allocation au niveau système. 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 19.3.1). Les paramètres adéquats du noyau sont nommés de façon cohérente parmi les différents systèmes ; le Tableau 19.1 donne un aperçu. Néanmoins, les méthodes pour les obtenir varient. Les suggestions pour quelques plateformes sont données ci-dessous.

Tableau 19.1. Paramètres System V IPC

Nom | Description | Valeurs nécessaires pour faire fonctionner une instance PostgreSQL
--- | --- | ---
`SHMMAX` | Taille maximum du segment de mémoire partagée (en octets) | au moins 1 ko, mais la valeur par défaut est normalement bien plus grande
`SHMMIN` | Taille minimum du segment de mémoire partagée (en octets) | 1
`SHMALL` | Total de la mémoire partagée disponible (en octets ou pages) | si octets, identique à `SHMMAX` ; si pages, `ceil(SHMMAX/PAGE_SIZE)`, plus de la marge pour les autres applications
`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 de la place pour les autres applications
`SEMMNI` | Nombre maximum d'identifiants de sémaphores (c'est-à-dire d'ensembles) | au moins `ceil((max_connections + autovacuum_max_workers + max_wal_senders + max_worker_processes + 6) / 16)` plus de la marge pour les autres applications
`SEMMNS` | nombre maximum de sémaphores répartis dans le système | `ceil((max_connections + autovacuum_max_workers + max_wal_senders + max_worker_processes + 6) / 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é.)

PostgreSQL requiert quelques octets de mémoire partagée System V (typiquement 48 octets sur des plateformes 64 bits) pour chaque copie du serveur. Sur la plupart des systèmes d'exploitation modernes, cette quantité est facilement allouable. Néanmoins, si vous exécutez plusieurs copies du serveur ou si vous le configurez explicitement pour utiliser de grandes quantités de mémoire partagée System V (voir shared_memory_type et dynamic_shared_memory_type), il pourrait être nécessaire d'augmenter `SHMALL`, correspondant à la quantité totale de mémoire partagée System V pour tout le système. Notez que `SHMALL` est en nombre de blocs disques, et non pas en nombre d'octets sur de nombreux 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 32 octets 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.

Lors de l'utilisation de sémaphores System V, PostgreSQL utilise un sémaphore par connexion autorisée (max_connections), par processus autovacuum worker autorisé (autovacuum_max_workers), par processus WAL sender autorisé (max_wal_senders) et par processus en tâche de fond autorisé réclamant un accès à la mémoire partagée, le tout 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 `autovacuum_max_workers` plus `max_wal_senders` plus `max_worker_processes`, plus 1 encore pour chacune des 16 connexions autorisées, plus les workers (voir la formule dans le Tableau 19.1). Le paramètre `SEMMNI` détermine la limite du nombre d'ensembles de sémaphores qui peuvent exister sur le système à un instant précis. Ce paramètre doit donc être au moins égal à `ceil((max_connections + autovacuum_max_workers + max_wal_senders + max_worker_processes + 6) / 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`. Si le système dispose de ce paramètre (ce n'est pas le cas pour beaucoup d'entre eux), il définit la taille de la carte de ressources de sémaphores, dans laquelle chaque bloc contigu de sémaphores disponibles a besoin d'une entrée. Lorsqu'un ensemble de sémaphores est libéré, soit il est ajouté à une entrée existante, soit il est enregistré sous une nouvelle entrée dans la 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 peut mener au fil du temps à rendre moins de sémaphores disponibles qu'il ne devrait y avoir.

D'autres paramètres en relation avec l'« annulation de sémaphores », tels que `SEMMNU` et `SEMUME`, n'affectent pas PostgreSQL.

Lors de l'utilisation de sémaphores POSIX, le nombre de sémaphores nécessaires est le même que pour System V, c'est-à-dire un sémaphore par connexion autorisée (max_connections), par processus autovacuum worker autorisé (autovacuum_max_workers), par processus WAL sender autorisé (max_wal_senders) et par processus en tâche de fond (max_worker_processes). Sur les plateformes où cette option est préférée, le noyau ne spécifie pas de limite au nombre de sémaphores POSIX.

AIX

  Il ne doit plus être nécessaire de faire une configuration spéciale pour les paramètres tels que `SHMMAX`, car c'est configuré de façon à ce que toute la mémoire puisse être utilisée en tant que mémoire partagée. C'est le type de configuration habituellement utilisée pour d'autres bases de données comme DB/2.

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

FreeBSD

  Les paramètres par défaut de mémoire partagée sont en général suffisant, sauf si vous affectez `shared_memory_type` à `sysv`. Les sémaphores System V ne sont pas utilisés sur cette plateforme.

  Les paramètres IPC par défaut peuvent être modifiés en utilisant la commande `sysctl` ou `loader`. Les paramètres suivants peuvent être configurés en utilisant `sysctl` :

      # sysctl kern.ipc.shmall=32768
      # sysctl kern.ipc.shmmax=134217728

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

  Si vous avez affecté `shared_memory_type` à `sysv`, vous pourriez aussi vouloir configurer votre noyau pour verrouiller la mémoire partagée System V en RAM et l'empêcher d'être envoyé dans le swap. Ceci peut être accompli en utilisant le paramètre `kern.ipc.shm_use_phys` de `sysctl`.

  Dans une prison FreeBSD, il vous est recommandé de configurer le paramètre `sysvshm` à `new`, ainsi il a son propre espace de nommage de mémoire partagée System V. (Avant FreeBSD 11.0, il était nécessaire d'activer l'accès partagé à l'espace de nommage IPC de l'hôte depuis les prisons, et prendre les mesures pour éviter les collisions.)

NetBSD

  La configuration par défaut de la mémoire partagée est en général suffisante, sauf si vous avez affecté `shared_memory_type` à `sysv`. Dans ce cas, vous voudrez habituellement augmenter `kern.ipc.semmni` et `kern.ipc.semmns` car les valeurs par défaut de ces paramètres sur NetBSD sont bien trop bas.

  Les paramètres IPC peuvent être ajustés en utilisant `sysctl`. Par exemple :

      # sysctl -w kern.ipc.semmni=100

  Pour que ce paramètrage persiste après un redémarrage, modifiez le fichier `/etc/sysctl.conf`.

  Si vous avez configuré `shared_memory_type` à `sysv`, vous pourriez aussi vouloir configurer votre noyau pour verrouiller la mémoire partagée System V en RAM et prévenir la mémoire d'être envoyée sur swap. Ceci peut être accompli en utilisant le paramètre `kern.ipc.shm_use_phys`de la commande `sysctl`.

OpenBSD

  La configuration par défaut de la mémoire partagée est en général suffisante, sauf si vous avez configuré `shared_memory_type` à `sysv`. Vous voudrez habituellement augmenter `kern.seminfo.semmni` et `kern.seminfo.semmns` car les valeurs par défaut de ces paramètres sur OpenBSD sont bien trop bas.

  Les paramètres IPC peuvent être ajustés en utilisant `sysctl`, par exemple :

      # sysctl kern.seminfo.semmni=100

  Pour rendre ce paramétrage persistant entre les redémarrages, modifiez `/etc/sysctl.conf`.

HP-UX

  Les paramètres par défaut tendent à suffire pour des installations normales.

  Les paramètres IPC peuvent être initialisés dans System Administration Manager (SAM) sous Kernel Configuration → Configurable Parameters. Choisissez Create A New Kernel une fois terminé.

Linux

  La configuration par défaut de la mémoire partagée est en général suffisante, sauf si vous avez configuré `shared_memory_type` à `sysv`, et uniquement sur les anciennes versions de noyau fournies avec des valeurs par défaut trop basses. Les sémaphores de System V ne sont pas utilisés sur cette plateforme.

  La configuration de la taille de mémoire partagée peut être modifiée avec l'interface proposée par la commande `sysctl`. Par exemple, pour permettre l'utilisation de 16 Go :

      $ sysctl -w kernel.shmmax=17179869184
      $ sysctl -w kernel.shmall=4194304

  Pour rendre ce paramètrage persistant entre les redémarrages, voir `/etc/sysctl.conf`.

macOS

  La configuration par défaut de la mémoire partagée et des sémaphores est en général suffisante, sauf si vous avez configuré `shared_memory_type` à `sysv`.

  La méthode recommandée pour configurer la mémoire partagée sous macOS est de 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

  Notez que, dans certaines versions de macOS, les cinq paramètres de mémoire partagée doivent être configurés dans `/etc/sysctl.conf`, sinon les valeurs seront ignorées.

  `SHMMAX` peut seulement être configuré avec un multiple exact de 4096.

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

  Il est possible de tous les modifier en ligne sauf `SHMMNI`, grâce à sysctl. Mais il est toujours préférable de configurer vos valeurs préférées dans `/etc/sysctl.conf`, pour que les nouvelles valeurs soient conservées après un redémarrage.

Solaris
illumos

  La configuration de la mémoire partagée et des sémaphores par défaut sont habituellement suffisamment bonnes pour la majorité des configurations de PostgreSQL. La valeur par défaut de Solaris pour `SHMMAX` correspond maintenant à un quart de la mémoire disponible sur le système. Pour configurer plus finement ce paramètre, vous devez utiliser une configuration de projet associé à l'utilisateur `postgres`. Par exemple, exécutez ce qui suit en tant qu'utilisateur `root` :

      projadd -c "PostgreSQL DB User" -K "project.max-shm-memory=(privileged,8GB,deny)" -U postgres -G postgres user.postgres

  Cette commande ajoute le projet `user.postgres` et configure le maximum de mémoire partagée pour l'utilisateur `postgres` à 8 Go. Cela prend effet à chaque fois que l'utilisateur se connecte et quand vous redémarrez PostgreSQL. La ligne ci-dessus suppose que PostgreSQL est exécuté par l'utilisateur `postgres` dans le groupe `postgres`. Aucun redémarrage du serveur n'est requis.

  Sur un serveur de bases de données ayant beaucoup de connexions, les autres modifications recommandées pour le noyau sont :

      project.max-shm-ids=(priv,32768,deny)
      project.max-sem-ids=(priv,4096,deny)
      project.max-msg-ids=(priv,4096,deny)

  De plus, si vous exécutez PostgreSQL dans une zone, vous pourriez avoir besoin d'augmenter les limites d'utilisation des ressources pour la zone. Voir Chapter2: Projects and Tasks dans System Administrator's Guide pour plus d'informations sur les `projets` et `prctl`.

### 19.4.2. systemd RemoveIPC

Si systemd est utilisé, certaines précautions sont de mise pour que les ressources IPC (incluant la mémoire partagée) ne soient pas supprimées par le système d'exploitation. Cela est particulièrement important lors de l'installation de PostgreSQL via les sources. Les utilisateurs de versions packagées par la distribution ont moins de chance d'être affectés, l'utilisateur `postgres` étant habituellement créé en tant qu'utilisateur système.

Le paramètre `RemoveIPC` dans `logind.conf` contrôle si les objets IPC sont supprimés lors de déconnexion complète d'un utilisateur. Les utilisateurs système sont exclus. Ce paramètre est par défaut actif sur la version originale de systemd, mais certaines distributions positionnent ce paramètre à off.

Un effet typique observé quand ce paramètre est activé est que les objets en mémoire partagée utilisés pour l'exécution des requêtes en parallèle sont supprimés à des moments en apparence aléatoires, amenant ainsi des erreurs et messages d'avertissement lors des tentatives de les ouvrir ou supprimer, comme :

    WARNING:  could not remove shared memory segment "/PostgreSQL.1450751626": No such file or directory

Différents types d'objets IPC (mémoire partagée et sémaphores, System V et POSIX) sont traités de manière légèrement différente par systemd, et l'on peut observer que certaines ressources IPC ne sont pas supprimées de la même manière que les autres. Il n'est toutefois pas conseillé de compter sur ces subtiles différences.

Une « déconnexion utilisateur » peut survenir lors d'une opération de maintenance ou manuellement lorsqu'un administrateur se connecte avec le compte `postgres` ou un compte similaire, ce qui est difficile à éviter en général.

Ce qu'est un « utilisateur système » est déterminé à la compilation de systemd par le paramètre `SYS_UID_MAX` dans `/etc/login.defs`.

Les scripts de packaging et déploiement devront faire attention à créer l'utilisateur `postgres` en tant qu'utilisateur système avec `useradd -r`, `adduser --system`, ou une commande équivalente.

Sinon, si le compte utilisateur a été créé de manière incorrecte ou ne peut être modifié, il est recommandé de configurer

    RemoveIPC=no

dans `/etc/systemd/logind.conf` ou un autre fichier de configuration approprié.

### Attention

Au moins une de ces deux choses doit être garantie, sinon le serveur PostgreSQL ne pourra être considéré comme fiable.

### 19.4.3. 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, le paramètre noyau `fs.file-max` détermine le nombre maximum de fichiers ouverts que le noyau supportera. Ce nombre est modifiable avec `sysctl -w fs.file-max=`N``. Pour rendre la configuration persistante après un redémarrage, ajouter cette affectation dans le fichier `/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.

Une autre limite du noyau qui pourrait avoir un impact pour accepter un très grand nombre de connexions est la longueur maximale de la queue de connexion du socket. Si un plus grand nombre de demandes de connexion arrive dans une petite période de temps, certaines pourraient être rejetées avant que le processus postmaster ne puisse traiter les demandes, avec des clients recevant des messages d'erreurs de connexion qui aident peu à résoudre le problème (par exemple « Resource temporarily unavailable » ou « Connection refused », en français respectivement « Ressource temporairement indisponible » ou « Connexion refusée ». La longueur limite de la queue par défaut est de 128 sur un grand nombre de plateformes. Pour l'augmenter, ajustez le paramètre noyau approprié avec sysctl, puis redémarrez postmaster. Le paramètre a différents noms : `net.core.somaxconn` sous Linux, `kern.ipc.soacceptqueue` sous les FreeBSD récents, et `kern.ipc.somaxconn` sur macOS et d'autres variantes BSD.

### 19.4.4. Linux memory overcommit

Le comportement par défaut de la mémoire virtuelle sur Linux 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 principal, « postmaster ») si les demandes de mémoire de PostgreSQL ou 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. S'il y a peu de mémoire, augmenter la swap peut aider à éviter le problème car un système peut tuer des processus lorsque la mémoire physique et la mémoire swap sont utilisées entièrement.

Si PostgreSQL lui-même est la cause d'un manque de mémoire du système, vous pouvez éviter le problème en modifiant votre configuration. Dans certains cas, baisser les paramètres de configuration de la mémoire peut aider, tout particulièrement `shared_buffers`, `work_mem` et `hash_mem_multiplier`. Dans d'autres cas, le problème peut être causé par l'autorisation d'un trop grand nombre de connexions au serveur de bases de données. Dans beaucoup de cas, il est préférable de réduire `max_connections` et d'utiliser à la place un logiciel de multiplexage de connexions (connection pooling).

Il est possible de modifier le comportement du noyau avec le « overcommit memory ». Bien que ce paramétrage n'empêchera pas ce comportement, il réduira sa fréquence de façon significative et contribuera du coup à un système plus robuste. Ceci se fait en sélectionnant le mode strict de l'overcommit 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 (https://www.kernel.org/doc/Documentation/vm/overcommit-accounting).

Une autre approche, qui peut aussi utiliser la modification de `vm.overcommit_memory`, est de configurer la valeur de la variable d'ajustement du score OOM, valeur par processus, pour le processus postmaster à `-1000`, garantissant ainsi qu'il ne sera pas la cible de OOM. La façon la plus simple de le faire est d'exécuter

    echo -1000 > /proc/self/oom_score_adj

dans le script de démarrage de postmaster juste avant d'appeler postmaster. Notez que cette action doit être faite en tant qu'utilisateur root. Dans le cas contraire, elle n'aura aucun effet. Du coup, un script de démarrage, exécuté par root, est le meilleur endroit où placer ce code. Si vous le faites, vous devriez aussi configurer ces variables d'environnement dans le script de démarrage avant d'invoquer le processus postmaster :

    export PG_OOM_ADJUST_FILE=/proc/self/oom_score_adj
    export PG_OOM_ADJUST_VALUE=0

Ces paramètres vont faire en sorte que les processus fils du postmaster s'exécuteront avec l'ajustement de score OOm normal (0), pour que l'OOM puisse encore les cibler si cela s'avère nécessaire. Vous pouvez utiliser d'autres valeurs pour `PG_OOM_ADJUST_VALUE` si vous voulez que les processus fils s'exécutent avec un autre ajustement de score. (`PG_OOM_ADJUST_VALUE` peut aussi être omis, auquel cas sa valeur par défaut est zéro.) Si vous ne voulez pas configurer `PG_OOM_ADJUST_FILE`, les processus fils s'exécuteront avec le même ajustement de score OOM que le processus père postmaster, ce qui n'est pas conseillé car le but est de s'assurer que le processus postmaster soit protégé par la configuration.

### 19.4.5. Pages mémoire de grande taille (huge pages) sous Linux

L'utilisation des huge pages réduit la surcharge lors de l'utilisation de gros morceaux contigus de mémoire, ce que fait PostgreSQL, tout particulièrement lors de l'utilisation de grosses valeurs pour shared_buffers. Pour activer cette fonctionnalité avec PostgreSQL, vous avez besoin d'un noyau compilé avec `CONFIG_HUGETLBFS=y` et `CONFIG_HUGETLB_PAGE=y`. Vous aurez aussi besoin de configurer le système d'exploitation pour qu'il fournisse suffisament de Huge Pages de la taille désirée. Le paramètre shared_memory_size_in_huge_pages, calculé à l'exécution renvoie le nombre de Huge Pages requis. Ce paramètre peut être visualisé avant de démarrer le serveur avec une commande `postgres` comme :

    $ postgres -D $PGDATA -C shared_memory_size_in_huge_pages
    $ grep ^Hugepagesize /proc/meminfo
    Hugepagesize:       2048 kB
    $ ls /sys/kernel/mm/hugepages
    hugepages-1048576kB  hugepages-2048kB

Dans cet exemple, la valeur par défaut est de 2 Mo, vous pouvez aussi demander explicitement soit 2 Mo soit 1 Go avec huge_page_size. Pour s'adapter au nombre de blocs calculés par `shared_memory_size_in_huge_pages`. Alors que nous avons besoin d'au moins `3170` Huge Pages dans cet exemple, une configuration plus importante serait appropriée si les autres programmes sur la machine ont besoin de Huge Pages eux-aussi. Nous pouvons les configurer avec :

    # sysctl -w vm.nr_hugepages=3170

N'oubliez pas d'ajouter cette configuration à `/etc/sysctl.conf` pour qu'elle soit appliquée à chaque redémarrage. Pour les tailles personnalisées de Huge Page, nous pouvons utiliser à la place :

    # echo 3170 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

Il est aussi possible de fournir ces paramètres au démarrage en utilisant les paramètres noyau tels que `hugepagesz=2M hugepages=3170`.

Parfois, le noyau n'est pas capable d'allouer immédiatement le nombre souhaité de huge pages à cause de la fragmentation, donc il peut être nécessaire de répéter cette commande ou de redémarrer. (Tout de suite après un redémarrage, la plupart de la mémoire de la machine doit être disponible à une conversion en huge pages.) Pour vérifier la situation au niveau de l'allocation des huge pages pour une taille donnée, utilisez :

    $ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

Il pourrait être nécessaire de donner le droit à l'utilisateur du système d'exploitation du serveur de bases de données en configurant `vm.hugetlb_shm_group` via sysctl, et/ou en donnant le droit de verrouiller la mémoire avec `ulimit -l`.

Il est aussi nécessaire de donner le droit d'utiliser les huge pages à l'utilisateur système qui exécute PostgreSQL. Cela se fait en configurant `vm.hugetlb_shm_group` via sysctl, et le droit de verrouiller la mémoire avec `ulimit -l`.

Le comportement par défaut pour les huge pages dans PostgreSQL est de les utiliser quand cela est possible, avec la taille par défaut des Huge Pages du système, et de revenir aux pages normales dans le cas contraire. Pour forcer l'utilisation des huge pages, vous pouvez configurer huge_pages à `on` dans le fichier `postgresql.conf`. Notez que, avec ce paramètre configuré ainsi, PostgreSQL refusera de démarrer s'il ne peut pas récupérer suffisamment de huge pages.

Pour une description détaillée des huge pages sous Linux, lisez https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.