MySQL falla cuando aumento el valor max_heap_table_size

MySQL falla cuando aumento el valor max_heap_table_size

Tengo una instancia de MySQL ejecutándose en un servidor Ubuntu 12.04, equipado con 120 GB de RAM. Hay varios scripts PHP ejecutándose en él, que a veces establecen nuevos parámetros de MySQL. Uno de estos scripts utiliza tablas de MEMORIA grandes para consolidar datos antes de insertarlos en tablas MySISAM.

Últimamente actualicé max_heap_table_size y tmp_table_size de 16 GB a 20 GB, para evitar errores de "tabla llena". Como resultado, MySQL falló durante la siguiente ejecución del script.

En realidad, primero generó un rastro de pista:

14:30:19 UTC - mysqld got signal 11 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.

key_buffer_size=536870912
read_buffer_size=131072
max_used_connections=85
max_threads=700
thread_count=82
connection_count=81
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 2055554 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.

Thread pointer: 0x7ff66dbb4f30
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 7ff632b80e60 thread_stack 0x28000
/usr/sbin/mysqld(my_print_stacktrace+0x29)[0x7ff66b087589]
/usr/sbin/mysqld(handle_fatal_signal+0x483)[0x7ff66af4c9d3]
/lib/x86_64-linux-gnu/libpthread.so.0(+0xfcb0)[0x7ff669c96cb0]
/usr/sbin/mysqld(_Z10field_convP5FieldS0_+0x37)[0x7ff66af49077]
/usr/sbin/mysqld(_ZN10Item_field13save_in_fieldEP5Fieldb+0x46)[0x7ff66af599b6]
/usr/sbin/mysqld(_Z11fill_recordP3THDPP5FieldR4ListI4ItemEb+0x4e)[0x7ff66adf3afe]
/usr/sbin/mysqld(_ZN12select_union9send_dataER4ListI4ItemE+0x6f)[0x7ff66aea705f]
/usr/sbin/mysqld(+0x32c554)[0x7ff66ae5a554]
/usr/sbin/mysqld(+0x3225cf)[0x7ff66ae505cf]
/usr/sbin/mysqld(_Z10sub_selectP4JOINP13st_join_tableb+0x7e)[0x7ff66ae5255e]
/usr/sbin/mysqld(+0x335274)[0x7ff66ae63274]
/usr/sbin/mysqld(_ZN4JOIN4execEv+0xc03)[0x7ff66ae72ec3]
/usr/sbin/mysqld(_Z12mysql_selectP3THDPPP4ItemP10TABLE_LISTjR4ListIS1_ES2_jP8st_orderSB_S2_SB_yP13select_resultP18st_select_lex_unitP13st_select_lex+0x130)[0x7ff66ae6e610]
/usr/sbin/mysqld(_Z21mysql_derived_fillingP3THDP3LEXP10TABLE_LIST+0x121)[0x7ff66ae13671]
/usr/sbin/mysqld(_Z20mysql_handle_derivedP3LEXPFbP3THDS0_P10TABLE_LISTE+0x68)[0x7ff66ae130f8]
/usr/sbin/mysqld(_Z20open_and_lock_tablesP3THDP10TABLE_LISTbjP19Prelocking_strategy+0x11a)[0x7ff66adf7c9a]
/usr/sbin/mysqld(+0x2fac95)[0x7ff66ae28c95]
/usr/sbin/mysqld(_Z21mysql_execute_commandP3THD+0x16a6)[0x7ff66ae307f6]
/usr/sbin/mysqld(_Z11mysql_parseP3THDPcjP12Parser_state+0x10f)[0x7ff66ae35a0f]
/usr/sbin/mysqld(_Z16dispatch_command19enum_server_commandP3THDPcj+0x1e71)[0x7ff66ae37951]
/usr/sbin/mysqld(_Z24do_handle_one_connectionP3THD+0x1bd)[0x7ff66aeddd9d]
/usr/sbin/mysqld(handle_one_connection+0x50)[0x7ff66aedde00]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x7e9a)[0x7ff669c8ee9a]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7ff6693bf3fd]

Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Query (7fea98004a80): is an invalid pointer
Connection ID (thread ID): 15144
Status: NOT_KILLED

The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.

El bloqueo/reinicio ocurrió una hora más tarde:

131122 15:30:24 [Warning] Using unique option prefix myisam-recover instead of myisam-recover-options is deprecated and will be removed in a future release. Please use the full name instead.
131122 15:30:24 [Warning] Using unique option prefix myisam-recover instead of myisam-recover-options is deprecated and will be removed in a future release. Please use the full name instead.
131122 15:30:24 [Note] Plugin 'FEDERATED' is disabled.
131122 15:30:24 InnoDB: The InnoDB memory heap is disabled
131122 15:30:24 InnoDB: Mutexes and rw_locks use GCC atomic builtins
131122 15:30:24 InnoDB: Compressed tables use zlib 1.2.3.4
131122 15:30:24 InnoDB: Initializing buffer pool, size = 128.0M
131122 15:30:24 InnoDB: Completed initialization of buffer pool
131122 15:30:24 InnoDB: highest supported file format is Barracuda.
InnoDB: Log scan progressed past the checkpoint lsn 1319218667
131122 15:30:24  InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.

Desafortunadamente, no tengo resultados de binlog o de registros de consultas lentas para publicar aquí, pero lo que puedo decir es que el script PHP continuó ejecutándose después de que se produjo el seguimiento de la pila. Se detuvo durante el reinicio de MySQL.

No se debe considerar una falla de hardware, ya que este error ya ocurrió en 2 servidores distintos.

¿Cuál podría ser la causa del accidente? ¿Cómo puedo saber el máximo max_heap_table_size y tmp_table_size que puedo usar sin bloquear mysql?

ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 1031141
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1031141
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

La versión de MySQL es 5.5.34 para Ubuntu 12.04,1.

Respuesta1

Con 120 GB de memoria, parece posible que su máquina también tenga múltiples CPU físicas y una arquitectura de acceso a memoria no uniforme (NUMA)... y si ese es el caso, podría tener mucha memoria disponible pero aún así, contrariamente a la intuición, No hay suficiente memoria disponible.

Si voy por el buen camino hasta ahora, podría encontrarse con este problema cuando MySQL intente aumentar la memoria asignada a la MEMORYtabla y encuentre un error relacionado con la forma en que Linux maneja las asignaciones de memoria cuando se ejecuta en esta arquitectura, solo con considerando la memoria disponible que se encuentra en las tarjetas de memoria que están conectadas directamente a una CPU en particular que fue elegida de manera un tanto arbitraria como "la única" desde la cual se atenderían las solicitudes de memoria, a pesar de que hay otra memoria física libre en otras partes de la placa base. .

NUMA está bien en teoría, pero quizás no sea ideal para procesos individuales que necesitan cantidades masivas de memoria, como es el caso de MySQL... pero hay una solución.

La solución será modificar el mysqld_safescript agregando esta línea:

cmd="/usr/bin/numactl --interleave all $cmd"

...inmediatamentedespuésesta línea...

cmd="$NOHUP_NICENESS"

Las razones se explican aquí, en un excelente artículo escrito originalmente para abordar por qué los servidores MySQL con esta arquitectura intercambiaban mucho a pesar de tener memoria libre; sin embargo, eso fue un síntoma de un problema más amplio que el autordespuésseñaló que "no es enteramente un problema de intercambio", que, incluso con el intercambio deshabilitado, podría incluir "asignaciones de memoria fallidas".

http://blog.jcole.us/2010/09/28/mysql-swap-insanity-and-the-numa-architecture/

Por supuesto, estoy especulando sobre si esto se aplica a su sistema, pero parece una posibilidad que vale la pena. Utilicé exactamente esta solución cuando encontré un problema en una nueva máquina de 128 GB cuando intenté aprovisionar un grupo de búfer InnoDB de 64 GB y MySQL no pudo encontrar 64 GB libres en una máquina connadamás corriendo. Cuando me di cuenta de que el valor más alto que podía usar con éxito era algo menos de 1/4 de la memoria total en una máquina de 16 núcleos con 4físicoprocesadores... algo así como con lo que parece que te estás topando... fue cuando junté las piezas en cuanto a la naturaleza del problema.

Respuesta2

La documentación paratmp_table_sizedice que esta configuración es el tamaño máximo que puede tener una tabla temporalen memoria. Exceder ese tamaño no genera errores de tabla completa; desencadena un cambio del uso de la tabla en la memoria al uso de una tabla MyISAM en el disco.

El sistema falla porque está permitiendo que las tablas temporales consuman mucha más memoria de la que deberían. Lo mismo con las tablas de memoria.

Deberías soltar el tmp_table_sizeformaabajo. Recuerde, esta configuración no es un máximo general. Es un máximo por tabla temporal. Si tiene 5 consultas que crean una tabla temporal enorme (digamos poco menos de 20 GB cada una), ahora tiene tablas temporales que utilizan hasta 100 GB de su RAM. Agregue un sexto y habrá usado más RAM de la que tiene el servidor en total.

Si sus secuencias de comandos realmente utilizan el motor de almacenamiento MEMORIA, luego escriba los datos en un archivo MyISAM después de considerar cambiarlo. Si realmente existe la necesidad de un rendimiento tan rápido en una tabla temporal tan grande, debería buscar un almacenamiento más rápido (por ejemplo,Fusión-io,viridenteet al). Si son excesivos o demasiado caros, al menos consideraría los SSD de consumo.

MyISAM funciona mejor cuando sus datos se almacenan en caché en la memoria del sistema (RAM no utilizada). Si sus scripts destruyen el caché cada vez que realizan una consulta enorme (usando el motor MEMORY), el rendimiento de MyISAM se verá afectado.

Sospecho que el script utiliza el motor de almacenamiento de MEMORIA para "mejorar" el rendimiento cuando en realidad lo está eliminando. Si es una tabla temporal, debería usar tablas temporales, y su tmp_table_size debería ser algo mucho más pequeño, obligándolo a guardarlo en el disco después de que rompa tmp_table_size.

Los valores predeterminados para max_heap_table_size y tmp_table_size son 16 MB. Si es posible, sugeriría cambiar la configuración a los valores predeterminados. Ajuste hacia arriba en pequeños incrementos mientras monitorea el uso de recursos (e/s de disco, uso total de memoria, uso de CPU, etc.) hasta que encuentre configuraciones que funcionen para su conjunto de datos.

información relacionada