Uno de los factores clave de un servidor de base de datos MySQL de alto rendimiento es tener una buena asignación y utilización de la memoria, especialmente cuando se ejecuta en un entorno de producción. Pero, ¿cómo puede determinar si la utilización de MySQL está optimizada? ¿Es razonable tener una alta utilización de la memoria o requiere un ajuste fino? ¿Qué pasa si me encuentro con una pérdida de memoria?
Veamos estos temas y mostremos las cosas que puede verificar en MySQL para determinar rastros de alta utilización de memoria.
Asignación de memoria en MySQL
Antes de profundizar en el título del tema específico, daré una breve información sobre cómo MySQL usa la memoria. La memoria juega un recurso importante para la velocidad y la eficiencia cuando se manejan transacciones simultáneas y se ejecutan consultas grandes. Cada subproceso en MySQL exige memoria que se utiliza para administrar las conexiones de los clientes, y estos subprocesos comparten la misma memoria base. Variables como thread_stack (pila para subprocesos), net_buffer_length (para el búfer de conexión y el búfer de resultados) o con max_allowed_packet donde la conexión y el resultado aumentarán dinámicamente hasta este valor cuando sea necesario, son variables que afectan la utilización de la memoria. Cuando ya no se necesita un subproceso, la memoria asignada a él se libera y se devuelve al sistema a menos que el subproceso vuelva a la caché de subprocesos. En ese caso, la memoria permanece asignada. Las uniones de consultas, las cachés de consultas, la clasificación, la caché de tablas y las definiciones de tablas requieren memoria en MySQL, pero se atribuyen con variables del sistema que puede configurar y configurar.
En la mayoría de los casos, las variables específicas de la memoria establecidas para una configuración están dirigidas a una configuración específica basada en el almacenamiento, como MyISAM o InnoDB. Cuando se genera una instancia de mysqld dentro del sistema host, MySQL asigna búferes y cachés para mejorar el rendimiento de las operaciones de la base de datos en función de los valores establecidos en una configuración específica. Por ejemplo, las variables más comunes que cada DBA establecerá en InnoDB son las variables innodb_buffer_pool_size e innodb_buffer_pool_instances, ambas relacionadas con la asignación de memoria del grupo de búfer que contiene datos en caché para las tablas de InnoDB. Es deseable si tiene mucha memoria y espera manejar grandes transacciones configurando innodb_buffer_pool_instances para mejorar la simultaneidad al dividir el grupo de búfer en varias instancias del grupo de búfer.
Mientras que para MyISAM, debe lidiar con key_buffer_size para manejar la cantidad de memoria que manejará el búfer de clave. MyISAM también asigna un búfer para cada subproceso concurrente que contiene una estructura de tabla, estructuras de columna para cada columna y se asigna un búfer de tamaño 3 * N (donde N es la longitud máxima de fila, sin contar las columnas BLOB). MyISAM también mantiene un búfer de fila adicional para uso interno.
MySQL también asigna memoria para tablas temporales a menos que sea demasiado grande (determinado por tmp_table_size y max_heap_table_size). Si está utilizando tablas de MEMORIA y la variable max_heap_table_size tiene un valor muy alto, esto también puede requerir una gran cantidad de memoria, ya que la variable de sistema max_heap_table_size determina cuánto puede crecer una tabla y no hay conversión al formato en disco.
MySQL también tiene un esquema de rendimiento que es una función para monitorear las actividades de MySQL a bajo nivel. Una vez que esto está habilitado, asigna memoria dinámicamente de forma incremental, escalando su uso de memoria a la carga real del servidor, en lugar de asignar la memoria requerida durante el inicio del servidor. Una vez que se asigna la memoria, no se libera hasta que se reinicia el servidor.
MySQL también se puede configurar para asignar grandes áreas de memoria para su grupo de búfer si usa Linux y si el kernel está habilitado para admitir páginas grandes, es decir, usando HugePages.
Qué verificar una vez que la memoria de MySQL es alta
Comprobar consultas en ejecución
Es muy común que los administradores de bases de datos de MySQL se familiaricen primero con lo que sucede con el servidor MySQL en ejecución. Los procedimientos más básicos son verificar la lista de procesos, verificar el estado del servidor y verificar el estado del motor de almacenamiento. Para hacer estas cosas, básicamente, solo tiene que ejecutar la serie de consultas iniciando sesión en MySQL. Ver a continuación:
Para ver las consultas en ejecución,
mysql> SHOW [FULL] PROCESSLIST;
Ver la lista de procesos actual revela consultas que se están ejecutando activamente o incluso procesos inactivos o inactivos. Es muy importante y es una rutina importante tener un registro de las consultas que se están ejecutando. Como se indicó sobre cómo MySQL asigna la memoria, las consultas en ejecución utilizarán la asignación de memoria y pueden causar problemas de rendimiento de manera drástica si no se controlan.
Ver las variables de estado del servidor MySQL,
mysql> SHOW SERVER STATUS\G
o filtrar variables específicas como
mysql> SHOW SERVER STATUS WHERE variable_name IN ('<var1>', 'var2'...);
Las variables de estado de MySQL sirven como su información estadística para obtener datos métricos para determinar cómo funciona su MySQL al observar los contadores proporcionados por los valores de estado. Hay ciertos valores aquí que le dan un vistazo que afecta la utilización de la memoria. Por ejemplo, verificar la cantidad de subprocesos, la cantidad de cachés de tablas o el uso del grupo de búfer,
...
| Created_tmp_disk_tables | 24240 |
| Created_tmp_tables | 334999 |
…
| Innodb_buffer_pool_pages_data | 754 |
| Innodb_buffer_pool_bytes_data | 12353536 |
...
| Innodb_buffer_pool_pages_dirty | 6 |
| Innodb_buffer_pool_bytes_dirty | 98304 |
| Innodb_buffer_pool_pages_flushed | 30383 |
| Innodb_buffer_pool_pages_free | 130289 |
…
| Open_table_definitions | 540 |
| Open_tables | 1024 |
| Opened_table_definitions | 540 |
| Opened_tables | 700887 |
...
| Threads_connected | 5 |
...
| Threads_cached | 2 |
| Threads_connected | 5 |
| Threads_created | 7 |
| Threads_running | 1 |
Ver el estado del monitor del motor, por ejemplo, el estado de InnoDB
mysql> SHOW ENGINE INNODB STATUS\G
El estado de InnoDB también revela el estado actual de las transacciones que procesa el motor de almacenamiento. Le brinda el tamaño de almacenamiento dinámico de una transacción, índices hash adaptables que revelan su uso de búfer o le muestra la información del grupo de búfer de innodb como en el siguiente ejemplo:
---TRANSACTION 10798819, ACTIVE 0 sec inserting, thread declared inside InnoDB 1201
mysql tables in use 1, locked 1
1 lock struct(s), heap size 1136, 0 row lock(s), undo log entries 8801
MySQL thread id 68481, OS thread handle 139953970235136, query id 681821 localhost root copy to tmp table
ALTER TABLE NewAddressCode2_2 ENGINE=INNODB
…
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 528, free list len 43894, seg size 44423, 1773 merges
merged operations:
insert 63140, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 553193, node heap has 1 buffer(s)
Hash table size 553193, node heap has 637 buffer(s)
Hash table size 553193, node heap has 772 buffer(s)
Hash table size 553193, node heap has 1239 buffer(s)
Hash table size 553193, node heap has 2 buffer(s)
Hash table size 553193, node heap has 0 buffer(s)
Hash table size 553193, node heap has 1 buffer(s)
Hash table size 553193, node heap has 1 buffer(s)
115320.41 hash searches/s, 10292.51 non-hash searches/s
...
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 2235564032
Dictionary memory allocated 3227698
Internal hash tables (constant factor + variable factor)
Adaptive hash index 78904768 (35404352 + 43500416)
Page hash 277384 (buffer pool 0 only)
Dictionary cache 12078786 (8851088 + 3227698)
File system 1091824 (812272 + 279552)
Lock system 5322504 (5313416 + 9088)
Recovery system 0 (0 + 0)
Buffer pool size 131056
Buffer pool size, bytes 2147221504
Free buffers 8303
Database pages 120100
Old database pages 44172
Modified db pages 108784
Pending reads 0
Pending writes: LRU 2, flush list 342, single page 0
Pages made young 533709, not young 181962
3823.06 youngs/s, 1706.01 non-youngs/s
Pages read 4104, created 236572, written 441223
38.09 reads/s, 339.46 creates/s, 1805.87 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 12 / 1000 not 5 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 120100, unzip_LRU len: 0
I/O sum[754560]:cur[8096], unzip sum[0]:cur[0]
…
Otra cosa para agregar, también puede usar Performance Schema y sys schema para monitorear el consumo y la utilización de la memoria por parte de su servidor MySQL. De forma predeterminada, la mayoría de las instrumentaciones están deshabilitadas de forma predeterminada, por lo que hay que hacer cosas manuales para usar esto.
Comprobar el intercambio
De cualquier manera, es probable que MySQL esté intercambiando su memoria a disco. A menudo, esta es una situación muy común, especialmente cuando el servidor MySQL y el hardware subyacente no están configurados de manera óptima en paralelo con los requisitos esperados. Hay ciertos casos en los que no se anticipó la demanda de tráfico, la memoria podría crecer cada vez más, especialmente si se ejecutan consultas incorrectas que consumen o utilizan mucho espacio de memoria y degradan el rendimiento, ya que los datos se recogen en el disco en lugar del búfer. Para verificar el intercambio, simplemente ejecute el comando freemem o vmstat como se muestra a continuación,
[[email protected] ~]# free -m
total used free shared buff/cache available
Mem: 3790 2754 121 202 915 584
Swap: 1535 39 1496
[[email protected] ~]# vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 40232 124100 0 937072 2 3 194 1029 477 313 7 2 91 1 0
0 0 40232 123912 0 937228 0 0 0 49 1247 704 13 3 84 0 0
1 0 40232 124184 0 937212 0 0 0 35 751 478 6 1 93 0 0
0 0 40232 123688 0 937228 0 0 0 15 736 487 5 1 94 0 0
0 0 40232 123912 0 937220 0 0 3 74 1065 729 8 2 89 0 0
También puede verificar usando procfs y recopilar información, como ir a /proc/vmstat o /proc/meminfo.
Uso de Perf, gdb y Valgrind con Massif
El uso de herramientas como perf, gdb y valgrind lo ayuda a profundizar en un método más avanzado para determinar la utilización de la memoria de MySQL. Hay momentos en que un resultado interesante se convierte en un misterio para resolver el consumo de memoria que lo lleva a su desconcierto en MySQL. Esto se convierte en la necesidad de tener más escepticismo y el uso de estas herramientas lo ayuda a investigar cómo MySQL está usando el manejo de la memoria, desde asignarla hasta utilizarla para procesar transacciones o procesos. Esto es útil, por ejemplo, si está observando que MySQL se está comportando de manera anormal, lo que podría causar una mala configuración o podría conducir a la detección de fugas de memoria.
Por ejemplo, usar perf en MySQL revela más información en un informe a nivel del sistema:
[[email protected] ~]# perf report --input perf.data --stdio
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 54K of event 'cpu-clock'
# Event count (approx.): 13702000000
#
# Overhead Command Shared Object Symbol
# ........ ....... ................... ...................................................................................................................................................................................................
#
60.66% mysqld [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore
2.79% mysqld libc-2.17.so [.] __memcpy_ssse3
2.54% mysqld mysqld [.] ha_key_cmp
1.89% mysqld [vdso] [.] __vdso_clock_gettime
1.05% mysqld mysqld [.] rec_get_offsets_func
1.03% mysqld mysqld [.] row_sel_field_store_in_mysql_format_func
0.92% mysqld mysqld [.] _mi_rec_pack
0.91% mysqld [kernel.kallsyms] [k] finish_task_switch
0.90% mysqld mysqld [.] row_search_mvcc
0.86% mysqld mysqld [.] decimal2bin
0.83% mysqld mysqld [.] _mi_rec_check
….
Dado que este puede ser un tema especial para profundizar, le sugerimos que consulte estos blogs externos realmente buenos como sus referencias, Perf Basics for MySQL Profiling, Finding MySQL Scaling Problems Using perf, o aprenda a depurar usando valgrind con macizo.
Forma eficiente de verificar la utilización de memoria de MySQL
Usar ClusterControl alivia las rutinas molestas, como revisar sus runbooks o incluso crear sus propios playbooks que le entregarían informes. En ClusterControl, tiene paneles (usando SCUMM) donde puede tener una descripción general rápida de su(s) nodo(s) MySQL. Por ejemplo, al ver el panel general de MySQL,
puede determinar cómo funciona el nodo MySQL,
Ve que las imágenes anteriores revelan variables que afectan la utilización de la memoria de MySQL. Puede verificar cómo las métricas para clasificar cachés, tablas temporales, subprocesos conectados, caché de consultas o motores de almacenamiento en el grupo de búfer de nodb o el búfer de clave de MyISAM.
El uso de ClusterControl le ofrece una herramienta de utilidad integral donde también puede verificar las consultas en ejecución para determinar los procesos (consultas) que pueden afectar la alta utilización de la memoria. Vea a continuación un ejemplo,
Ver las variables de estado de MySQL es muy fácil,
Incluso puede ir a Rendimiento -> Estado Innodb también para revelar el estado InnoDB actual de los nodos de su base de datos. Además, en ClusterControl, se detecta un incidente, intentará recopilar el incidente y muestra el historial como un informe que le proporciona el estado de InnoDB como se muestra en nuestro blog anterior sobre MySQL Freeze Frame.
Resumen
La resolución de problemas y el diagnóstico de su base de datos MySQL cuando se sospecha de una alta utilización de la memoria no es tan difícil, siempre y cuando conozca los procedimientos y las herramientas a utilizar. El uso de la herramienta adecuada le ofrece más flexibilidad y una productividad más rápida para entregar correcciones o soluciones con la posibilidad de obtener mejores resultados.