MySQL no libera memoria

8

MySQL parece querer mantener una tabla completa en caché (tamaño de tabla = ~ 20GB) después de que se realicen inserciones grandes o instrucciones de selección en ella. En este momento mi grupo de búferes innodb es de 20 GB. La RAM total es de 32 GB. Proporcionaré algo de uso de memoria y salida del estado innodb, así como salida de mysqltuner. Me ha estado volviendo loco durante los últimos días. ¡Por favor ayuda! Agradezco cualquier comentario y avíseme si necesita más información.

Además, realizar una 'TABLAS DE ENJUAGUE' solo se cierra y se vuelve a abrir en la memoria. Al menos creo que eso es lo que está sucediendo. Aquí está el estado actual de la memoria innodb antes de realizar un montón de inserciones:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 21978152960; in additional pool allocated 0
Dictionary memory allocated 6006471
Buffer pool size   1310719
Free buffers       347984
Database pages     936740
Old database pages 345808
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 78031, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 551887, created 384853, written 4733512
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 936740, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

mysqld porcentaje de uso de memoria: 60.9%

mysqld porcentaje de uso de memoria después de inserciones (registros de 1 mil): 63.3%

y luego después de más inserciones (3 mil registros): 70.2%

¿No debería tener un límite de aproximadamente 62.5% ? (20 / 32GB) ram total?

salida desde la parte superior ordenando mi uso de MEM:

top - 14:30:56 up 23:25,  3 users,  load average: 3.63, 2.31, 1.91
Tasks: 208 total,   4 running, 204 sleeping,   0 stopped,   0 zombie
Cpu(s): 96.0%us,  3.0%sy,  0.0%ni,  0.0%id,  1.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  28821396k total, 28609868k used,   211528k free,   138696k buffers
Swap: 33554428k total,    30256k used, 33524172k free,  1208184k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1228 mysql     20   0 25.1g  19g 5512 S   31 70.2  62:01.10 mysqld

Aquí está la salida de memoria innodb después de realizar estas inserciones:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 21978152960; in additional pool allocated 0
Dictionary memory allocated 6006471
Buffer pool size   1310719
Free buffers       271419
Database pages     1011886
Old database pages 373510
Modified db pages  4262
Pending reads 1
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 82521, not young 0
7.08 youngs/s, 0.00 non-youngs/s
Pages read 585218, created 426667, written 5192189
24.08 reads/s, 53.08 creates/s, 1135.07 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1011886, unzip_LRU len: 0
I/O sum[0]:cur[266], unzip sum[0]:cur[0]

Según el estado de innodb, la memoria total asignada es la misma, pero mi sistema operativo (Virtual Ubuntu Server 12.04) informa más uso de memoria que eso. El uso de memoria permanece igual y aquí lo estoy definiendo como el servicio MySQL que no 'libera' memoria. ¿Alguna sugerencia?

salida de mysqltuner.pl:

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MRG_MYISAM
[--] Data in MyISAM tables: 226M (Tables: 287)
[--] Data in InnoDB tables: 33G (Tables: 1000)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17)
[--] Data in MEMORY tables: 0B (Tables: 1)
[!!] Total fragmented tables: 959

-------- Security Recommendations  -------------------------------------------
[OK] All database users have passwords assigned

-------- Performance Metrics -------------------------------------------------
[--] Up for: 23h 14m 27s (1M q [14.603 qps], 6K conn, TX: 16B, RX: 1B)
[--] Reads / Writes: 46% / 54%
[--] Total buffers: 22.2G global + 2.7M per thread (151 max threads)
[OK] Maximum possible memory usage: 22.6G (82% of installed RAM)
[OK] Slow queries: 0% (6/1M)
[OK] Highest usage of available connections: 6% (10/151)
[OK] Key buffer size / total MyISAM indexes: 2.0G/58.7M
[OK] Key buffer hit rate: 100.0% (216M cached / 38K reads)
[OK] Query cache efficiency: 81.2% (799K cached / 984K selects)
[!!] Query cache prunes per day: 5561
[OK] Sorts requiring temporary tables: 4% (819 temp sorts / 16K sorts)
[!!] Temporary tables created on disk: 27% (6K on disk / 22K total)
[OK] Thread cache hit rate: 99% (11 created / 6K connections)
[!!] Table cache hit rate: 0% (97 open / 10K opened)
[OK] Open file limit used: 12% (129/1K)
[OK] Table locks acquired immediately: 99% (433K immediate / 433K locks)
[!!] InnoDB  buffer pool / data size: 20.0G/33.6G
[OK] InnoDB log waits: 0
-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    MySQL started within last 24 hours - recommendations may be inaccurate
    Enable the slow query log to troubleshoot bad queries
    When making adjustments, make tmp_table_size/max_heap_table_size equal
    Reduce your SELECT DISTINCT queries without LIMIT clauses
    Increase table_cache gradually to avoid file descriptor limits
    Read this before increasing table_cache over 64: http://bit.ly/1mi7c4C
Variables to adjust:
    query_cache_size (> 128M)
    tmp_table_size (> 128M)
    max_heap_table_size (> 16M)
    table_cache (> 431)
    innodb_buffer_pool_size (>= 33G)
Cherner
fuente

Respuestas:

8

Primero, eche un vistazo a InnoDB Architecture (cortesía de Percona CTP Vadim Tkachenko)

Arquitectura InnoDB

InnoDB

Su estado para el grupo de búferes dice

Tamaño de la agrupación de almacenamiento intermedio 1310719

Ese es su tamaño de búfer en páginas. Cada página es de 16K . Eso resulta 20G - 16K.

Tenga en cuenta lo siguiente: introdujo datos en el InnoDB Buffer Pool. Qué cambió ?

Buffer pool size   1310719 
Free buffers       271419 (It was 347984)
Database pages     1011886 (Is was 936740)
Old database pages 373510 (It was 345808)
Modified db pages  4262 (It was 0)

Además, tenga en cuenta la diferencia entre el tamaño de la agrupación de almacenamientos intermedios en las páginas.

1310719 (tamaño de agrupación de almacenamiento intermedio) - 1011886 (páginas de la base de datos) = 298833

Eso es 298833 páginas InnoDB. ¿Cuánto espacio es eso?

mysql> select FORMAT(((1310719  - 1011886) * 16384) / power(1024,3),3) SpaceUsed;
+-----------+
| SpaceUsed |
+-----------+
| 4.560     |
+-----------+

Eso es 4.56GB. Ese espacio se utiliza para la sección Insertar búfer del InnoDB Buffer Pool (también conocido como Change Buffer) . Esto se utiliza para mitigar los cambios en los índices no únicos en el archivo de espacio de tabla del sistema (que todos se conocen como ibdata1).

El motor de almacenamiento InnoDB gestiona los componentes internos del grupo de búferes. Por lo tanto, InnoDB nunca superará el 62.5% de RAM. Además, la RAM para el Buffer Pool nunca se devuelve.

¿De dónde viene el 70,2% de RAM?

Mire hacia atrás en la salida de mysqltuner.plestas líneas

[OK] Maximum possible memory usage: 22.6G (82% of installed RAM)
Key buffer size / total MyISAM indexes: 2.0G/58.7M
[--] Total buffers: 22.2G global + 2.7M per thread (151 max threads)

mysqld tiene tres formas principales de asignar RAM

Cualquier pequeño aumento en las conexiones DB aumentará la RAM más allá del umbral del 62.5% que ve para InnoDB.

MyISAM (Nota al margen)

Lo que me llama la atención es

Key buffer size / total MyISAM indexes: 2.0G/58.7M

Ya que tienes muy pocos índices para MyISAM. Puede establecer key_buffer_size en 64M.

No necesita reiniciar mysql para eso. Solo corre

SET GLOBAL ket_buffer_size = 1024 * 1024 * 64;

Luego, modifique esto en my.cnf

[mysqld]
key_Buffer_size = 64M

Esto le dará al sistema operativo 2GB de RAM. ¡Tu VM simplemente te amará por ello!

Darle una oportunidad !!!

CONSIDERACIÓN

Ejecutar FLUSH TABLESen tablas InnoDB simplemente cierra archivos contra los .ibdarchivos. Esto realmente no empujará los cambios directamente. Los cambios tienen que migrar a través de las tuberías de InnoDB. Es por eso que ves el pico Modified db pages. Las 4262 páginas cambiadas (66.59 MB) se enjuagan cuando InnoDB no programa su enjuague.

RolandoMySQLDBA
fuente
Muchas gracias por el análisis en profundidad. Tiene mucho más sentido ahora, ¿entonces es cierto que el grupo de búferes innodb se mantendrá con el uso máximo de memoria con el tiempo (20 GB)? ¿Y la memoria total que usará mysqld es del 82%?
cherner
Eso es un sí a ambas preguntas
RolandoMySQLDBA
@RolandoMySQLDBA, si entiendo bien, MySQL no libera la memoria y esto es lo que es. ¿No?
Malus
1
@MalusJan Mi respuesta no es sobre la liberación de memoria. Mi respuesta aborda la cantidad de RAM que se usa para StorageEngines y DB Connections. A veces, las conexiones de DB persistentes que no se cierran correctamente pueden retener la RAM asignada. Las memorias caché para los búferes de Storage Engine pueden redimensionarse dinámicamente para MyISAM (MySQL 5.x +) e InnoDB (MySQL 5.7+). Las memorias caché para las conexiones DB se pueden redimensionar dinámicamente para las nuevas conexiones entrantes (no las conexiones actualmente abiertas) La memoria que no se libera se debe a errores de pérdida de memoria en mysqld.
RolandoMySQLDBA
@RolandoMySQLDBA. En el servidor tenemos más de 10 bases de datos y necesitamos crear volcados todos los días y cada uno mysqldumptoma algo de memoria y no los libera. Entonces, después de todo el volcado, tenemos aproximadamente el 80% de la memoria RAM ocupada por el proceso mysql. ¿Tienes alguna solución para eso? Gracias
Malus Jan hace
0

Me he enfrentado a un tipo similar de problema. Pregunta: ¿está utilizando la configuración de memoria dividida? (THP y compartido) En caso afirmativo, desactive las páginas enormes y deje que MySQL maneje la memoria y siga monitoreándola. Compruebe también cuántos procesos paralelos se ejecutan en el servidor, incluidos los procesos en modo de suspensión. Si está utilizando la configuración de memoria compartida, entonces necesita más memoria para este servidor.

Raja Naveed
fuente