¿Por qué MySQL dice que no tengo memoria?

9

Estaba tratando de ejecutar un INSERT...SELECTMySQL bastante grande con JDBC, y obtuve la siguiente excepción:

Exception in thread "main" java.sql.SQLException: Out of memory (Needed 1073741824 bytes)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)

Como en realidad no estoy devolviendo un objeto ResultSet, pensé que el espacio de almacenamiento dinámico de Java no debería ser un problema. Sin embargo, intenté subirlo de todos modos y no sirvió de nada. Luego intenté ejecutar la declaración en MySQL Workbench y obtuve esencialmente lo mismo:

Error Code 5: Out of memory (Needed 1073741816 bytes)

Debería tener suficiente RAM para completar estas operaciones (suficiente para adaptarse a toda la tabla que estoy seleccionando), pero supongo que hay varias configuraciones que necesito ajustar para aprovechar toda mi memoria. Estoy ejecutando una instancia de Amazon EC2 High Memory Double Extra Large con un AMI de Windows Server 2008. He intentado jugar con el archivo my.ini para usar una mejor configuración, pero por lo que sé, podría haber empeorado las cosas. Aquí hay un volcado de ese archivo:

[client]
port=3306
[mysql]
default-character-set=latin1
[mysqld]
port=3306
basedir="C:/Program Files/MySQL/MySQL Server 5.5/"
datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
character-set-server=latin1
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=100
query_cache_size=1024M
table_cache=256
tmp_table_size=25G
thread_cache_size=8
myisam_max_sort_file_size=100G
myisam_repair_threads = 2
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_additional_mem_pool_size=26M
innodb_flush_log_at_trx_commit=2
innodb_log_buffer_size=13M
innodb_buffer_pool_size=23G
innodb_log_file_size=622M
innodb_thread_concurrency=18
innodb_file_per_table=TRUE
join_buffer_size=4G
max_heap_table_size = 10G

Entonces, ¿es solo una cuestión de cambiar la configuración anterior para que funcione mejor para mi entorno? Si es así, ¿qué configuración debo usar? Soy el único que usa esta instancia; Lo uso para mi proyecto de pasatiempo personal que implica el análisis estadístico de grandes conjuntos de datos. Como tal, soy libre de dejar que consuma todos los recursos disponibles para mis propias consultas.

Si no se trata de cambiar esa configuración, ¿cuál es el problema? Gracias por cualquier ayuda que pueda ofrecer sobre cómo configurar mejor todo.

Michael McGowan
fuente
Cualquier persona que use 1g de caché de consulta no tiene idea de lo que está haciendo.
@winmutt Es muy posible que tengas razón, pero tu comentario no ayuda a nadie sin más explicaciones. ¿Podrías ayudarnos dando razones para tu sentimiento?
Michael McGowan
Una herramienta útil para comenzar es tools.percona.com/wizard
KCD

Respuestas:

9

Dado que esta es una instalación de Windows, @DTest aún proporcionó la dirección inicial correcta.

Aplica la siguiente fórmula:

La mayoría de la gente usa esto:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + (read_buffer_size + sort_buffer_size) X max_connections

Prefiero esto:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + ((read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size) X max_connections)

Estas variables son las que necesita ajustar hasta que la fórmula rinda el 80% de la RAM instalada o menos.

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
RolandoMySQLDBA
fuente
4

Intentaría reducir el tamaño de tu buffer. Hacerlos tan grandes como los tenga va a causar problemas. ¿Cuánta memoria tiene disponible para ejecutar estos valores?

query_cache_size=1024M
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_buffer_pool_size=23G

Algunos de los tamaños de búfer se asignan por subproceso, por ejemplo myisam_sort_buffer_size de 10G asigna 10G para cada subproceso.

Primero reduciría drásticamente esos valores, y luego investigaría qué valores realmente necesita tener tanta RAM asignada (si corresponde).

Derek Downey
fuente
4

Una manera rápida de determinar cuánta memoria MySQL cree que podría asignar es la siguiente:

wget mysqltuner.pl

perl mysqltuner.pl

Cuando ejecute este script, le dirá qué porcentaje de la RAM instalada MySQL cree que puede asignar de forma segura. Si la respuesta dada es superior al 100%, definitivamente debe reducir el tamaño de su búfer. Los principales en los que centrarse son:

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
key_buffer_size (no es realmente efectivo después de 4G)

@DTest ya estableció la dirección para ti en su respuesta, entonces +1 para su respuesta. El script perl le dirá qué sucede si no lo configura o si cambia algún valor. Aquí hay un ejemplo:

Un cliente mío tiene
read_buffer_size = 128K
read_rnd_buffer_size = 256K
sort_buffer_size = 2M
join_buffer_size = 128K
max_connections = 1050

Aquí está la salida de mysqltuner.pl:

MySQLTuner 1.2.0 - Principales
informes de Hayden Bug, solicitudes de características y descargas en http://mysqltuner.com/
Ejecutar con '--help' para opciones adicionales y filtrado de salida
Ingrese su inicio de sesión administrativo MySQL: lwdba
Ingrese su administrador MySQL contraseña:

-------- Estadísticas Generales ---------------------------------------- ----------
[-] Verificación de la versión omitida para el script MySQLTuner
[OK] Actualmente se está ejecutando la versión compatible de MySQL 5.0.51a-community-log
[!!] Cambie al sistema operativo de 64 bits - MySQL no puede usar actualmente toda tu RAM

-------- Estadísticas del motor de almacenamiento --------------------------------------- ----
[-] Estado: + Archivo -BDB + Federado + InnoDB -ISAM -NDBCluster
[-] Datos en tablas MyISAM: 319M (Tablas: 108)
[-] Datos en tablas InnoDB: 2M (Tablas: 5)
[!!] Tablas fragmentadas totales: 22

-------- Métricas de rendimiento ---------------------------------------- ---------
[-] Hasta: 52d 23h 15m 57s (72M q [15.875 qps], 241K conn, TX: 2B, RX: 1B)
[-] Lecturas / escrituras: 59% / 41%
[-] Buffers totales: 34.0M global + 2.7M por hilo (1050 hilos máx.)
[!!] Asignar> 2GB RAM en sistemas de 32 bits puede causar inestabilidad del sistema
[!!] Uso máximo de memoria posible: 2.8G (72% de la RAM instalada)
[OK] Consultas lentas: 0% (54 / 72M)
[OK] Mayor uso de las conexiones disponibles: 6% (65/1050)
[OK] Tamaño del búfer clave / total de índices MyISAM: 8.0M / 82.1M
[OK] Tasa de aciertos del búfer clave: 100.0% (4B en caché / 1M de lecturas)
[!!] La caché de consultas está deshabilitada
[OK] Clasificaciones que requieren tablas temporales: 0% (0 clasificaciones temporales / 948K clasificaciones)
[OK] Tablas temporales creadas en disco: 3% (11K en disco / 380K en total)
[!!] El caché de subprocesos está deshabilitado
[!!] Tasa de aciertos de caché de tabla: 0% (64 abierto / 32K abierto)
[OK] Abrir archivo límite utilizado: 2% (125 / 5K)
[OK] Bloqueos de tabla adquiridos inmediatamente: 99% (30M inmediatos / 30M bloqueos)
[OK] Tamaño de datos InnoDB / grupo de búfer: 2.7M / 8.0M

-------- Recomendaciones ----------------------------------------- ------------
Recomendaciones generales:
Ejecute OPTIMIZE TABLE para desfragmentar tablas para un mejor rendimiento
Habilite el registro lento de consultas para solucionar las consultas incorrectas
Establezca thread_cache_size en 4 como valor inicial
Aumente gradualmente table_cache gradualmente para evitar los límites del descriptor de archivo
Variables para ajustar:
query_cache_size (> = 8M)
thread_cache_size (comienza en 4)
table_cache (> 64)

Tenga en cuenta las métricas de rendimiento

[-] Buffers totales: 34.0M global + 2.7M por hilo (1050 hilos máximo)

que MySQL puede asignar hasta el 72% de la RAM instalada en función de la configuración en /etc/my.cnf.

El 34M se basa en innodb_buffer_pool_size y key_buffer_size combinados

El 2.7M por hilo se basó en read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size.

Los múltiplos de 2.7M están basados ​​en max_ connections.

Por lo tanto, debe modificar estos parámetros hasta que el informe de métricas de rendimiento indique que tiene menos del 100% (preferiblemente menos del 80%) de RAM instalada.

RolandoMySQLDBA
fuente
No estoy seguro de poder usar tu herramienta; Estoy usando Windows La documentación mencionaba que Windows no es compatible, pero lo intenté de todos modos. Cuando intenté ejecutarlo, indicó que no podía encontrar mysqladmin en mi $ PATH, pero el directorio bin de MySQL está en mi $ PATH.
Michael McGowan
Lo siento, no noté el datadir de Windows. Agregaré una respuesta diferente.
RolandoMySQLDBA
1

¿No dijiste cuánta RAM tienes? Supongo que es al menos 32 GB.

innodb_buffer_pool_size - 23G

Bueno para tanta RAM.

query_cache_size = 1G

Demasiado grande. Es ineficiente cuando es grande. Recomendar no más de 50M.

key-buffer_size = 5G

Podría haber un límite estricto de 4G (todavía) en Windows, tenía un límite rígido de 4G. Su 5G puede haberse convertido en 1G. De todos modos, si todas sus tablas son InnoDB, ¿por qué desperdiciar el ram? Ajústelo a 50M.

Dado que el mensaje de error tenía exactamente 1G, huele a sort_buffer_size. 32M podría ser razonable.

Rick James
fuente