Optimiza el consumo elevado de memoria en las instancias

Es un problema común tener instancias que consumen mucha memoria o que generan problemas de memoria insuficiente (OOM). Una instancia de base de datos que se ejecuta con una utilización de memoria alta suele causar problemas de rendimiento, atascos o, incluso, tiempo de inactividad de la base de datos.

Algunos bloques de memoria de MySQL se usan en todo el mundo. Esto significa que todas las cargas de trabajo de consultas comparten ubicaciones de memoria, están ocupadas todo el tiempo y se liberan solo cuando se detiene el proceso de MySQL. Algunos bloques de memoria se basan en sesiones, lo que significa que apenas la sesión se cierra, la memoria que utiliza esa sesión también se libera y se devuelve al sistema.

Cuando una instancia de Cloud SQL para MySQL tiene un uso de memoria alto, Cloud SQL recomienda que identifiques la consulta o el proceso que usa mucha memoria y liberes esa memoria. El consumo de memoria de MySQL se divide en tres partes principales:

  • Consumo de subprocesos y memoria
  • Consumo de memoria del búfer
  • Consumo de memoria de la caché

Consumo de subprocesos y memoria

Cada sesión de usuario consume memoria según las consultas que se ejecutan, los búferes o la caché que usa esa sesión, y se controla mediante los parámetros de sesión de MySQL. Los parámetros principales incluyen lo siguiente:

  • thread_stack
  • net_buffer_length
  • read_buffer_size
  • read_rnd_buffer_size
  • sort_buffer_size
  • join_buffer_size
  • max_heap_table_size
  • tmp_table_size

Si hay N cantidad de consultas en ejecución en un momento determinado, cada consulta consume memoria de acuerdo con estos parámetros durante la sesión.

Consumo de memoria del búfer

Esta parte de la memoria es común para todas las consultas y se controla mediante parámetros como Innodb_buffer_pool_size, Innodb_log_buffer_size y key_buffer_size.

Consumo de memoria de la caché

La memoria caché incluye una caché de consultas, que se usa para guardar las consultas y sus resultados, lo que permite lograr una recuperación de datos más rápida de las mismas consultas con posterioridad. También incluye la caché binlog para contener los cambios realizados en el registro binario mientras se ejecuta la transacción, y binlog_cache_size la controla.

Otros consumos de memoria

La memoria también se usa para las operaciones de unión y orden. Si tus consultas usan operaciones de orden o unión, esas consultas usan memoria en función de join_buffer_size y sort_buffer_size.

Además, si habilitas el esquema de rendimiento, consume memoria. Para verificar el uso de memoria del esquema de rendimiento, usa la siguiente consulta:

SELECT *
FROM
  performance_schema.memory_summary_global_by_event_name
WHERE EVENT_NAME LIKE 'memory/performance_schema/%';

Existen muchos instrumentos disponibles en MySQL que puedes configurar para supervisar el uso de memoria a través del esquema de rendimiento. Para obtener más información, consulta la documentación de MySQL.

El parámetro relacionado con MyISAM para la inserción de datos masivos es bulk_insert_buffer_size.

Para obtener información sobre cómo MySQL usa memoria, consulta la documentación de MySQL.

Recomendaciones

Usa el Explorador de métricas para identificar el uso de memoria

Puedes revisar el uso de memoria de una instancia con la métrica database/memory/components.usage en el Explorador de métricas.

Si tienes menos de un 5% de memoria combinada en database/memory/components.cache y database/memory/components.free, el riesgo de un evento de OOM es alto. Para supervisar el uso de memoria y evitar eventos de OOM, te recomendamos que configures una política de alertas con una condición de límite de métrica del 95% o más en database/memory/components.usage.

En la siguiente tabla, se muestra la relación entre la memoria de tu instancia y el límite de alertas recomendado:

Memoria de la instancia Umbral de alertas recomendado
Hasta 100 GB 95%
De 100 GB a 200 GB 96%
De 200 GB a 300 GB 97%
Más de 300 GB 98%

Calcula el consumo de memoria

Calcula el uso máximo de memoria de tu base de datos de MySQL a fin de seleccionar el tipo de instancia adecuado para tu base de datos de MySQL. Usa la siguiente fórmula:

Uso máximo de memoria de MySQL = innodb_buffer_pool_size + innodb_additional_mem_pool_size + innodb_log_buffer_size + tmp_table_size + key_buffer_size + ((read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size) x max_connections)

Estos son los parámetros que se usan en la fórmula:

  • innodb_buffer_pool_size: es el tamaño en bytes del grupo de búferes, el área de la memoria en la que InnoDB almacena en caché los datos de la tabla y los índices.
  • innodb_additional_mem_pool_size: es el tamaño en bytes de un grupo de memoria que InnoDB usa para almacenar información del diccionario de datos y otras estructuras de datos internas.
  • innodb_log_buffer_size: es el tamaño en bytes del búfer que InnoDB usa para escribir en los archivos de registro en el disco.
  • tmp_table_size: es el tamaño máximo de las tablas temporales internas en memoria que creó el motor de almacenamiento MEMORY y, a partir de MySQL 8.0.28, el motor de almacenamiento TempTable.
  • Key_buffer_size: es el tamaño del búfer que se usa para los bloques de índice. Los bloques de índice para las tablas MyISAM se almacenan en búfer y se comparten en todos los subprocesos.
  • Read_buffer_size: cada subproceso que realiza un análisis secuencial para una tabla MyISAM asigna un búfer de este tamaño (en bytes) para cada tabla que analiza.
  • Read_rnd_buffer_size: esta variable se usa para las lecturas de tablas MyISAM, para cualquier motor de almacenamiento y para la optimización de lectura de varios rangos.
  • Sort_buffer_size: cada sesión que debe realizar un orden asigna un búfer de este tamaño. sort_buffer_size no es específico de ningún motor de almacenamiento y se aplica de forma general para la optimización.
  • Join_buffer_size: es el tamaño mínimo del búfer que se usa para los análisis de índices sin formato, los análisis de índices de rango y las uniones que no usan índices y, por lo tanto, realizan análisis de tablas completos.
  • Max_connections: es la cantidad máxima permitida de conexiones simultáneas de clientes.

Soluciona problemas de consumo elevado de memoria

  • Ejecuta SHOW PROCESSLIST para ver las consultas en curso que consumen memoria en este momento. Muestra todos los subprocesos conectados y sus instrucciones de SQL en ejecución actualmente y, luego, intenta optimizarlas. Presta atención a las columnas de estado y duración.

    mysql> SHOW [FULL] PROCESSLIST;
    
    
  • Verifica SHOW ENGINE INNODB STATUS en la sección BUFFER POOL AND MEMORY para ver el uso actual del grupo de búferes y la memoria, lo que puede ayudarte a configurar el tamaño del grupo de búferes.

    mysql> SHOW ENGINE INNODB STATUS \G
    ----------------------
    BUFFER POOL AND MEMORY
    ----------------------
    Total memory allocated 398063986; in additional pool allocated 0
    Dictionary memory allocated 12056
    Buffer pool size 89129
    Free buffers 45671
    Database pages 1367
    Old database pages 0
    Modified db pages 0
    
  • Usa el comando SHOW variables de MySQL para verificar los valores del contador, que te brindan información como la cantidad de tablas temporales, la cantidad de subprocesos, la cantidad de cachés de tablas, las páginas sucias, las tablas abiertas y el uso del grupo de búferes.

    mysql> SHOW variables like 'VARIABLE_NAME'
    

Aplicar cambios

Después de analizar el uso de memoria de diferentes componentes, configura la marca adecuada en tu base de datos de MySQL. Para cambiar la marca en la instancia de Cloud SQL para MySQL, puedes usar la consola de Google Cloud o la CLI de gcloud. Para cambiar el valor de la marca con la consola de Google Cloud, edita la sección Marcas, selecciona la marca y, luego, ingresa el valor nuevo.

Por último, si el uso de memoria sigue siendo alto y crees que las consultas y los valores de marcas están optimizados, considera aumentar el tamaño de la instancia para evitar eventos OOM.