Bonnes pratiques pour la gestion de l'utilisation de la mémoire

Cette page explique comment configurer l'utilisation de la mémoire pour une instance Cloud SQL.

Introduction

Lorsque vous créez une instance Cloud SQL, vous sélectionnez une quantité de mémoire pour cette instance. À mesure que la charge de travail d'une base de données PostgreSQL augmente, l'utilisation de la mémoire de l'instance augmente. Les instances qui consomment beaucoup de mémoire peuvent créer un goulot d'étranglement qui peut parfois entraîner des problèmes de mémoire insuffisante.

Lorsqu'une instance Cloud SQL manque de mémoire en raison d'une demande accrue, cela peut entraîner un temps d'arrêt de la base de données. Par conséquent, il est important de configurer correctement la mémoire de l'instance et les options de base de données liées à la mémoire, et de surveiller l'utilisation de la mémoire afin que l'instance fonctionne correctement.

Les composants de mémoire PostgreSQL sont généralement divisés en deux sections :

  • Mémoire globale : mémoire partagée entre tous les processus pour exécuter des requêtes Par exemple, shared_buffers et max_connections.
  • Mémoire locale : mémoire dédiée attribuée à chaque connexion. Par exemple, work_mem, maintenance_work_mem et temp_buffers.

Pour en savoir plus sur les autres configurations, consultez les pages Bonnes pratiques générales et Consignes opérationnelles.

Utilisation de la mémoire et options

Lorsque les instances Cloud SQL utilisent beaucoup de mémoire, les questions suivantes peuvent se poser :

  • Quelle requête ou quel processus utilise beaucoup de mémoire ?
  • Les paramètres de mémoire sont-ils suffisants pour l'activité de la base de données ?
  • Comment modifier les paramètres de mémoire ?

Lorsqu'une base de données PostgreSQL est en fonctionnement, l'utilisation de la mémoire est liée principalement aux éléments suivants :

  • Tampon partagé : il s'agit de la mémoire partagée allouée par PostgreSQL afin de contenir les données de table pour les opérations read et write. Pour l'opération read, toutes les données demandées à partir du disque sont d'abord extraites dans la RAM, puis transmises au client. De même, dans PostgreSQL, lorsque les données sont demandées (par exemple SELECT * from emp), elles sont d'abord extraites du disque vers shared_buffers pour la mise en cache, puis transmises au client. Il en va de même pour l'opération write.

    Le tampon partagé est également la zone de mémoire partagée dédiée à tous les processus et connexions pour les activités de base de données, telles que la mise en cache de données, la mise en cache de connexions et les opérations LMD (langage de manipulation de données). Le maximum que cette zone peut allouer est spécifié par l'option shared_buffers, et la valeur par défaut est fixée à 33 % de la mémoire de l'instance. Si la valeur de shared_buffers est élevée, la taille des données mises en cache est élevée.

  • Mémoire de travail de requête : lorsqu'une requête est exécutée, PostgreSQL alloue de la mémoire locale pour chaque opération, telle que le tri et le hachage. Le maximum qu'il peut allouer pour chaque opération d'une requête avant d'écrire dans les fichiers de disque temporaires est configuré par l'option work_mem, et la valeur par défaut est de 4 Mo. Si la valeur de work_mem est élevée, la quantité de données pouvant être triées en mémoire est élevée.
  • Mémoire de travail de maintenance : certaines opérations de maintenance telles que VACUUM, CREATE INDEX, ALTER TABLE et ADD FOREIGN KEY nécessitent une mémoire locale distincte allouée par PostgreSQL. La quantité maximale pour le processus backend que ces opérations utilisent peut être configurée par l'option maintenance_work_mem, et la valeur par défaut est de 64 Mo. Notez que les nœuds de calcul autovacuum utilisent également la mémoire de travail de maintenance et le maximum peut être remplacé par l'option autovacuum_work_mem. Si la valeur de maintenance_work_mem est élevée, la vitesse d'exécution de l'opération VACUUM est élevée.
  • Tampons temporaires : lorsqu'une table temporaire est utilisée dans une session de base de données, PostgreSQL alloue des tampons temporaires pour contenir la table temporaire locale de la session. La quantité maximale peut être spécifiée par l'option temp_buffers, et la valeur par défaut est de 8 Mo.
  • Connexion à la base de données : lorsqu'un client se connecte à la base de données, PostgreSQL crée un processus backend pour livrer la session client. En plus de la mémoire nécessaire à l'exécution de la requête, PostgreSQL alloue de la mémoire supplémentaire pour gérer des informations telles que le cache du catalogue système et les plans de requête préparés. Le nombre maximum de connexions simultanées autorisées au serveur de base de données peut être configuré par l'option max_connections. Chaque connexion inactive utilise environ 2 Mo à 3 Mo de mémoire partagée. Si la valeur de max_connections est élevée, l'instance peut établir d'autres connexions, mais au détriment de la mémoire.

Pour obtenir la liste complète des composants de mémoire dans PostgreSQL, consultez la documentation PostgreSQL. Pour modifier les options listées dans cette section, consultez la page Configurer des options de base de données.

Surveiller l'utilisation de la mémoire

Surveillez régulièrement la mémoire de votre instance dans Cloud Monitoring et maintenez-la en dessous de la limite de mémoire. Une bonne pratique consiste à définir une alerte dans Cloud Monitoring pour être averti lorsque la mémoire dépasse 90 % d'utilisation pendant 6 heures. Cette alerte peut vous avertir lorsque votre utilisation de la mémoire est constamment proche de la limite.

Surveillez également les incidents dus à une mémoire insuffisante. Pour ce faire, configurez une métrique basée sur les journaux pour le message server process .* was terminated by signal 9: Killed dans Cloud Monitoring afin de comptabiliser les événements de saturation de la mémoire, puis alerter à chaque fois qu'un tel événement se produit.

Si votre instance utilise constamment plus de 90 % de la capacité de mémoire ou si un événement de saturation de la mémoire se produit, vous pouvez augmenter la mémoire de l'instance. Vous pouvez également réduire l'utilisation de la mémoire en limitant le nombre de connexions à la base de données ou en diminuant les options de base de données, telles que shared_buffers, work_mem ou max_connections. Diminuer ces options peut limiter les performances de votre instance.

Mémoire insuffisante

En cas de mémoire insuffisante pour gérer la charge de travail de la base de données, le système d'exploitation Linux sous-jacent utilise en dernier recours out-of-memory (OOM) killer pour mettre fin à un processus afin de libérer de la mémoire. Cloud SQL est configuré de sorte que OOM killer ne cible que les processus de nœud de calcul PostgreSQL. Le processus postmaster est quant à lui préservé, de sorte qu'il lui suffit de mettre fin à toutes les connexions existantes à la base de données et d'exécuter une récupération pour protéger son intégrité. Si cela se produit, la base de données subit des interruptions de service et des temps d'arrêt. Dans le journal de la base de données PostgreSQL, des messages de ce type s'affichent :

2021-10-24 23:34:22.265 UTC [7]: [663-1] db=,user= LOG: server process (PID 1255039) was terminated by signal 9: Killed
2021-10-24 23:34:22.265 UTC [7]: [664-1] db=,user= DETAIL: Failed process was running: SELECT * FROM tab ORDER BY col
2021-10-24 23:34:22.277 UTC [7]: [665-1] db=,user= LOG: terminating any other active server processes
2021-10-24 23:34:22.278 UTC [1255458]: [1-1] db=postgres,user=postgres WARNING: terminating connection because of crash of another server process
2021-10-24 23:34:22.278 UTC [1255458]: [2-1] db=postgres,user=postgres DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
2021-10-24 23:34:22.278 UTC [1255458]: [3-1] db=postgres,user=postgres HINT: In a moment you should be able to reconnect to the database and repeat your command.
2021-10-24 23:34:22.278 UTC [1255458]: [4-1] db=postgres,user=postgres CONTEXT: while updating tuple (27,18) in relation "tab"
...
2021-10-24 23:34:22.558 UTC [1255477]: [1-1] db=postgres,user=postgres FATAL: the database system is in recovery mode
...
2021-10-24 23:34:25.579 UTC [7]: [666-1] db=,user= LOG: all server processes terminated; reinitializing
...
2021-10-24 23:34:25.691 UTC [1255482]: [1-1] db=,user= LOG: database system was interrupted; last known up at 2021-10-24 23:31:53 UTC
2021-10-24 23:34:25.776 UTC [1255482]: [2-1] db=,user= LOG: database system was not properly shut down; automatic recovery in progress
2021-10-24 23:34:25.789 UTC [1255482]: [3-1] db=,user= LOG: redo starts at 227/AB359400
2021-10-24 23:34:38.957 UTC [1255482]: [4-1] db=,user= LOG: redo done at 229/4621F508
2021-10-24 23:34:38.959 UTC [1255482]: [5-1] db=,user= LOG: last completed transaction was at log time 2021-10-24 23:34:18.5535+00
2021-10-24 23:34:39.290 UTC [7]: [667-1] db=,user= LOG: database system is ready to accept connections

Étapes suivantes