Prácticas recomendadas para administrar el uso de la memoria

En esta página, se describe cómo configurar el uso de memoria para una instancia de Cloud SQL.

Introducción

Cuando creas una instancia de Cloud SQL, debes seleccionar la cantidad de memoria para la instancia. A medida que aumenta la carga de trabajo de una base de datos de PostgreSQL, aumenta el uso de memoria de la instancia. Las instancias que consumen mucha memoria pueden crear un cuello de botella de rendimiento que a veces puede causar problemas de falta de memoria.

Cuando una instancia de Cloud SQL se queda sin memoria debido a una mayor demanda, puede causar el tiempo de inactividad de la base de datos. Por lo tanto, es importante configurar la memoria de la instancia y las marcas de la base de datos relacionadas con la memoria de manera adecuada y supervisar el uso de la memoria para que la instancia funcione en buen estado.

En términos generales, los componentes de la memoria de PostgreSQL se dividen en dos secciones:

  • Memoria global: se comparte en todos los procesos para ejecutar consultas. Por ejemplo, shared_buffers y max_connections.
  • Memoria local: es la memoria dedicada asignada a cada conexión. Por ejemplo, work_mem, maintenance_work_mem y temp_buffers.

Para obtener más consideraciones sobre la configuración, consulta Prácticas recomendadas generales y Lineamientos operativos.

Uso y marcas de memoria

Cuando las instancias de Cloud SQL tienen un uso de memoria alto, pueden surgir las siguientes preguntas:

  • ¿Qué consulta o proceso usa una cantidad elevada de memoria?
  • ¿La configuración de la memoria es adecuada para la actividad de la base de datos?
  • ¿Cómo se cambia la configuración de la memoria?

Cuando una base de datos de PostgreSQL funciona, la mayor parte del uso de memoria se produce en algunas áreas:

  • Búfer compartido: Es la memoria compartida que PostgreSQL asigna para conservar datos de la tabla de operaciones read y write. Para la operación read, cualquier dato que se solicite del disco se recupera primero a la RAM y, luego, se le proporciona al cliente. Del mismo modo, en PostgreSQL, cuando se solicitan los datos (por ejemplo, SELECT * from emp), primero se recuperan del disco a shared_buffers para el almacenamiento en caché y, luego, se entregan al cliente. Lo mismo sucede con la operación write.

    El búfer compartido también es el área de memoria compartida para todos los procesos y conexiones de las actividades de la base de datos, como el almacenamiento en caché de datos, el almacenamiento en caché de conexiones y las operaciones de lenguaje de manipulación de datos (DML). La marca shared_buffers especifica el máximo que esta área puede asignar, y el valor predeterminado es el 33% de la memoria de la instancia. Si el valor de shared_buffers es alto, el tamaño de los datos almacenados en caché es alto.

  • Memoria de trabajo de consulta: A medida que se ejecuta una consulta, PostgreSQL asigna memoria local para cada operación, como la clasificación y el hashing. El máximo que puede asignar a cada operación de una consulta antes de escribir en los archivos de discos temporales se configura con la marca work_mem, y el valor predeterminado es 4 MB. Si el valor de work_mem es alto, la cantidad de datos que se pueden ordenar en la memoria es alta.
  • Memoria del trabajo de mantenimiento: algunas operaciones de mantenimiento, como VACUUM, CREATE INDEX, ALTER TABLE y ADD FOREIGN KEY, requieren una memoria local separada que asigna PostgreSQL. La cantidad máxima del proceso de backend que se usa para estas operaciones se puede configurar con la marca maintenance_work_mem y el valor predeterminado es de 64 MB. Ten en cuenta que los trabajadores de vaciado también usan la memoria de trabajo de mantenimiento y el máximo se puede anular mediante la marca autovacuum_work_mem. Si el valor de maintenance_work_mem es alto, la velocidad de rendimiento de la operación VACUUM es alta.
  • Búferes temporales: Cuando se usa una tabla temporal en una sesión de base de datos, PostgreSQL asigna búferes temporales para contener la tabla temporal local de la sesión. La cantidad máxima se puede especificar con la marca temp_buffers y el valor predeterminado es de 8 MB.
  • Conexión de base de datos: Cuando un cliente se conecta a la base de datos, PostgreSQL crea un proceso de backend para entregar la sesión del cliente. Además de la memoria para ejecutar la consulta, PostgreSQL asigna memoria adicional a fin de mantener la información como la caché del catálogo del sistema y los planes de consultas preparados. La cantidad máxima de conexiones simultáneas permitidas al servidor de la base de datos se puede configurar con la marca max_connections. Cada conexión inactiva usa aproximadamente 2 MB o 3 MB de memoria compartida. Si el valor de max_connections es alto, la instancia puede realizar más conexiones, pero a costa de la memoria.

Para obtener una lista completa de los componentes de memoria en PostgreSQL, consulta la documentación de PostgreSQL. Para cambiar o modificar las marcas que se enumeran en esta sección, consulta Configura marcas de base de datos.

Supervisa el uso de memoria

Supervisa la memoria de tu instancia en Cloud Monitoring con regularidad y mantenla por debajo del límite de memoria. Se recomienda configurar una alerta en Cloud Monitoring a fin de alertar cuando el uso supere el 90% del límite durante 6 horas. Esta alerta puede advertirte cuando tu uso de memoria está cerca del límite constantemente.

Además, se supervisan los incidentes de memoria insuficiente. A fin de hacerlo, configura una métrica basada en registros para el mensaje server process .* was terminated by signal 9: Killed en Cloud Monitoring a fin de contar los eventos de memoria insuficiente y, luego, alertar cada vez que suceda un evento de este tipo.

Si la instancia opera de forma constante por encima del 90% del límite de memoria o de que se produzca un evento de memoria insuficiente, puedes aumentar la memoria de la instancia. De manera alternativa, puedes reducir el uso de memoria si limitas la cantidad de conexiones de base de datos o disminuyes las marcas de base de datos, como shared_buffers, work_mem o max_connections. Disminuir estas marcas puede limitar el rendimiento de la instancia.

Out of memory

Cuando no hay suficiente memoria para manejar la carga de trabajo de la base de datos, como último recurso, el sistema operativo Linux subyacente usa out-of-memory (OOM) killer para finalizar un proceso y liberar memoria. Cloud SQL está configurado para que el OOM killer se oriente solo a los procesos del trabajador de PostgreSQL. El proceso postmaster se conserva en esta situación para que solo tenga que finalizar todas las conexiones de base de datos existentes y ejecutar una recuperación a fin de proteger la integridad de la base de datos. Si esto sucede, hay momentos de interrupción del servicio y tiempo de inactividad en la base de datos. En el registro de la base de datos de PostgreSQL, aparecen mensajes como los siguientes:

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

¿Qué sigue?