¿Qué tan grande debe ser mysql innodb_buffer_pool_size?

170

Tengo una base de datos ocupada con únicamente tablas InnoDB que tiene un tamaño de aproximadamente 5 GB. La base de datos se ejecuta en un servidor Debian usando discos SSD y he establecido conexiones máximas = 800 que a veces saturan y muelen el servidor para detenerlo. La consulta promedio por segundo es de aproximadamente 2.5K. Por lo tanto, necesito optimizar el uso de memoria para hacer espacio para las conexiones máximas posibles.

He visto sugerencias de que innodb_buffer_pool_size debería ser hasta el 80% de la memoria total. Por otro lado, recibo esta advertencia del script tuning-primer:

Max Memory Ever Allocated : 91.97 G
Configured Max Per-thread Buffers : 72.02 G
Configured Max Global Buffers : 19.86 G
Configured Max Memory Limit : 91.88 G
Physical Memory : 94.58 G

Aquí están mis variables innodb actuales:

| innodb_adaptive_flushing                          | ON                                                                                                                     |
| innodb_adaptive_hash_index                        | ON                                                                                                                     |
| innodb_additional_mem_pool_size                   | 20971520                                                                                                               |
| innodb_autoextend_increment                       | 8                                                                                                                      |
| innodb_autoinc_lock_mode                          | 1                                                                                                                      |
| innodb_buffer_pool_instances                      | 1                                                                                                                      |
| innodb_buffer_pool_size                           | 20971520000                                                                                                            |
| innodb_change_buffering                           | all                                                                                                                    |
| innodb_checksums                                  | ON                                                                                                                     |
| innodb_commit_concurrency                         | 0                                                                                                                      |
| innodb_concurrency_tickets                        | 500                                                                                                                    |
| innodb_data_file_path                             | ibdata1:10M:autoextend                                                                                                 |
| innodb_data_home_dir                              |                                                                                                                        |
| innodb_doublewrite                                | ON                                                                                                                     |
| innodb_fast_shutdown                              | 1                                                                                                                      |
| innodb_file_format                                | Antelope                                                                                                               |
| innodb_file_format_check                          | ON                                                                                                                     |
| innodb_file_format_max                            | Antelope                                                                                                               |
| innodb_file_per_table                             | ON                                                                                                                     |
| innodb_flush_log_at_trx_commit                    | 2                                                                                                                      |
| innodb_flush_method                               | O_DIRECT                                                                                                               |
| innodb_force_load_corrupted                       | OFF                                                                                                                    |
| innodb_force_recovery                             | 0                                                                                                                      |
| innodb_io_capacity                                | 200                                                                                                                    |
| innodb_large_prefix                               | OFF                                                                                                                    |
| innodb_lock_wait_timeout                          | 50                                                                                                                     |
| innodb_locks_unsafe_for_binlog                    | OFF                                                                                                                    |
| innodb_log_buffer_size                            | 4194304                                                                                                                |
| innodb_log_file_size                              | 524288000                                                                                                              |
| innodb_log_files_in_group                         | 2                                                                                                                      |
| innodb_log_group_home_dir                         | ./                                                                                                                     |
| innodb_max_dirty_pages_pct                        | 75                                                                                                                     |
| innodb_max_purge_lag                              | 0                                                                                                                      |
| innodb_mirrored_log_groups                        | 1                                                                                                                      |
| innodb_old_blocks_pct                             | 37                                                                                                                     |
| innodb_old_blocks_time                            | 0                                                                                                                      |
| innodb_open_files                                 | 300                                                                                                                    |
| innodb_purge_batch_size                           | 20                                                                                                                     |
| innodb_purge_threads                              | 0                                                                                                                      |
| innodb_random_read_ahead                          | OFF                                                                                                                    |
| innodb_read_ahead_threshold                       | 56                                                                                                                     |
| innodb_read_io_threads                            | 4                                                                                                                      |
| innodb_replication_delay                          | 0                                                                                                                      |
| innodb_rollback_on_timeout                        | OFF                                                                                                                    |
| innodb_rollback_segments                          | 128                                                                                                                    |
| innodb_spin_wait_delay                            | 6                                                                                                                      |
| innodb_stats_method                               | nulls_equal                                                                                                            |
| innodb_stats_on_metadata                          | ON                                                                                                                     |
| innodb_stats_sample_pages                         | 8                                                                                                                      |
| innodb_strict_mode                                | OFF                                                                                                                    |
| innodb_support_xa                                 | ON                                                                                                                     |
| innodb_sync_spin_loops                            | 30                                                                                                                     |
| innodb_table_locks                                | ON                                                                                                                     |
| innodb_thread_concurrency                         | 4                                                                                                                      |
| innodb_thread_sleep_delay                         | 10000                                                                                                                  |
| innodb_use_native_aio                             | ON                                                                                                                     |
| innodb_use_sys_malloc                             | ON                                                                                                                     |
| innodb_version                                    | 1.1.8                                                                                                                  |
| innodb_write_io_threads                           | 4                                                                                                                      |

Una nota al margen que podría ser relevante: veo que cuando trato de insertar una publicación grande (por ejemplo, más de 10 KB) de Drupal (que se encuentra en un servidor web separado) a la base de datos, dura para siempre y la página no vuelve correctamente.

Con respecto a esto, me pregunto cuál debería ser mi innodb_buffer_pool_size para un rendimiento óptimo. Agradezco sus sugerencias para establecer este y otros parámetros de manera óptima para este escenario.

Alfish
fuente

Respuestas:

252

Su innodb_buffer_pool_size es enorme. Lo tienes establecido en 20971520000. Eso es 19.5135 GB. Si solo tiene 5 GB de datos e índices de InnoDB, entonces solo debería tener unos 8 GB. Incluso esto puede ser demasiado alto.

Esto es lo que deberías hacer. Primero ejecuta esta consulta

SELECT CEILING(Total_InnoDB_Bytes*1.6/POWER(1024,3)) RIBPS FROM
(SELECT SUM(data_length+index_length) Total_InnoDB_Bytes
FROM information_schema.tables WHERE engine='InnoDB') A;

Esto le dará el RIBPS, el tamaño recomendado de InnoDB Buffer Pool basado en todos los datos e índices de InnoDB con un 60% adicional.

Por ejemplo

mysql>     SELECT CEILING(Total_InnoDB_Bytes*1.6/POWER(1024,3)) RIBPS FROM
    ->     (SELECT SUM(data_length+index_length) Total_InnoDB_Bytes
    ->     FROM information_schema.tables WHERE engine='InnoDB') A;
+-------+
| RIBPS |
+-------+
|     8 |
+-------+
1 row in set (4.31 sec)

mysql>

Con esta salida, establecería lo siguiente en /etc/my.cnf

[mysqld]
innodb_buffer_pool_size=8G

Próximo, service mysql restart

Después del reinicio, ejecute mysql durante una semana o dos. Luego, ejecute esta consulta:

SELECT (PagesData*PageSize)/POWER(1024,3) DataGB FROM
(SELECT variable_value PagesData
FROM information_schema.global_status
WHERE variable_name='Innodb_buffer_pool_pages_data') A,
(SELECT variable_value PageSize
FROM information_schema.global_status
WHERE variable_name='Innodb_page_size') B;

Esto le dará cuántos GB reales de memoria está usando InnoDB Data en el InnoDB Buffer Pool en este momento.

He escrito sobre esto antes: ¿Qué configurar innodb_buffer_pool y por qué ...?

Puede ejecutar esta DataGBconsulta ahora mismo en lugar de reconfigurar, reiniciar y esperar una semana.

Este valor DataGBse parece más a lo grande que debe ser el InnoDB Buffer Pool + (porcentaje especificado en innodb_change_buffer_max_size). Estoy seguro de que será mucho menos que el 20000M que ha reservado en este momento. Los ahorros en RAM se pueden usar para ajustar otras cosas como

CAVEAT # 1

Es muy importante tener esto en cuenta: a veces, InnoDB puede requerir un 10% adicional sobre el valor para innodb_buffer_pool_size . Esto es lo que dice la documentación de MySQL sobre esto:

Cuanto mayor sea este valor, menos E / S de disco se necesita para acceder a los datos en las tablas. En un servidor de base de datos dedicado, puede configurarlo hasta en un 80% del tamaño de la memoria física de la máquina. Esté preparado para reducir este valor si se producen estos otros problemas:

La competencia por la memoria física puede causar paginación en el sistema operativo.

InnoDB reserva memoria adicional para memorias intermedias y estructuras de control, de modo que el espacio total asignado es aproximadamente un 10% mayor que el tamaño especificado.

El espacio de direcciones debe ser contiguo, lo que puede ser un problema en los sistemas Windows con archivos DLL que se cargan en direcciones específicas.

El tiempo para inicializar el grupo de búferes es aproximadamente proporcional a su tamaño. En instalaciones grandes, este tiempo de inicialización puede ser significativo. Por ejemplo, en un servidor Linux x86_64 moderno, la inicialización de un grupo de búferes de 10 GB tarda aproximadamente 6 segundos. Consulte la Sección 8.9.1, "El InnoDB Buffer Pool" .

CUEVA # 2

Veo los siguientes valores en su my.cnf

| innodb_io_capacity                                | 200 |
| innodb_read_io_threads                            | 4   |
| innodb_thread_concurrency                         | 4   |
| innodb_write_io_threads                           | 4   |

Estos números impedirán que InnoDB acceda a múltiples núcleos

Por favor configure lo siguiente:

[mysqld]
innodb_io_capacity = 2000
innodb_read_io_threads = 64
innodb_thread_concurrency = 0
innodb_write_io_threads = 64

He escrito sobre esto antes en el DBA StackExchange

Acabo de responder una pregunta como esta en ServerFault usando una fórmula más concisa :

SELECT CONCAT(CEILING(RIBPS/POWER(1024,pw)),SUBSTR(' KMGT',pw+1,1))
Recommended_InnoDB_Buffer_Pool_Size FROM
(
    SELECT RIBPS,FLOOR(LOG(RIBPS)/LOG(1024)) pw
    FROM
    (
        SELECT SUM(data_length+index_length)*1.1*growth RIBPS
        FROM information_schema.tables AAA,
        (SELECT 1.25 growth) BBB
        WHERE ENGINE='InnoDB'
    ) AA
) A;
RolandoMySQLDBA
fuente
1
¡Gracias por este gran mensaje! Su fórmula que comienza con SELECT (PagesData*PageSize)/POWER(1024,3) DataGB FROM...genera el siguiente error en MySQL 5.7: " La función 'INFORMATION_SCHEMA.GLOBAL_STATUS' está deshabilitada; consulte la documentación de 'show_compatibility_56' ". ¿Tendrías una versión actualizada por casualidad?
Benjamin
Obtengo 307 RIBPS y 264G. ¿Eso significa que necesito 307 GB de RAM?
E_Blue
Más como 264G. Pero debe tener suficiente RAM para eso, de lo contrario, dele el 80% mencionado de su RAM a mysql, dependiendo de qué más se ejecute en el sistema.
sjas
2
¡La mejor publicación que he leído! Tengo una ~ gran base de datos de alrededor de 3 GB. Después de leer su respuesta / artículo y la velocidad de los enlaces llegó a 2x
fat_mike
44
@Benjamin: a partir de MySQL 5.7.6, la información_esquema se fusiona en rendimiento_esquema. Así que simplemente cambie "information_schema" a "performance_schema" en la consulta para que funcione. Fuente: dev.mysql.com/doc/refman/5.7/en/status-table.html
Ralph Bolton
11

¿Algo como esto? Usando SHOW VARIABLESy SHOW GLOBAL STATUS:

Expresión: innodb_buffer_pool_size / _ram
Significado: % de RAM utilizada para InnoDB buffer_pool
Rango recomendado: 60 ~ 80%

Expresión: Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests
Significado: Leer solicitudes que tuvieron que llegar al disco
Rango recomendado: 0-2%
Qué hacer si está fuera de rango: Aumente innodb_buffer_pool_size si tiene suficiente RAM.

Expresión: Innodb_pages_read / Innodb_buffer_pool_read_requests
Significado: Leer las solicitudes que tuvieron que llegar al disco
Rango recomendado: 0-2%
Qué hacer si está fuera de rango: Aumente innodb_buffer_pool_size si tiene suficiente RAM.

Expresión: Innodb_pages_written / Innodb_buffer_pool_write_requests
Significado: Escribir solicitudes que tuvieron que llegar al disco
Rango recomendado: 0-15%
Qué hacer si está fuera del rango: Compruebe innodb_buffer_pool_size

Expresión: Innodb_buffer_pool_reads / Uptime
Significado: Lecturas
Rango recomendado: 0-100 / seg.
¿Qué hacer si está fuera de rango: aumentar innodb_buffer_pool_size?

Expresión: (Innodb_buffer_pool_reads + Innodb_buffer_pool_pages_flushed) / Uptime
Significado: InnoDB I / O
Rango recomendado: 0-100 / seg.
¿Qué hacer si está fuera de rango: aumentar innodb_buffer_pool_size?

Expresión: Innodb_buffer_pool_pages_flushed / Uptime
Significado: Escrituras (enjuagues)
Rango recomendado: 0-100 / seg.
¿Qué hacer si está fuera de rango: aumentar innodb_buffer_pool_size?

Expresión: Innodb_buffer_pool_wait_free / Uptime
Significado: Contador para cuando no hay páginas libres en buffer_pool. Es decir, todas las páginas están sucias.
Rango recomendado: 0-1 / seg.
Qué hacer si está fuera de rango: Primero asegúrese de que innodb_buffer_pool_size esté configurado razonablemente; si aún tiene problemas, disminuya innodb_max_dirty_pages_pct

Rick James
fuente
Gracias @Rick por el bonito comentario. ¿Qué innodb_buffer_pool_sizevalor especifica? ¿Tamaño real o configurado?
bromista
1
@joker: innodb_buffer_pool_sizeindica el tamaño máximo. En un servidor típico, el "grupo de búferes" comienza pequeño, pero rápidamente crece hasta ese tamaño máximo y permanece allí. Nota: Si eso es más grande que RAM (o incluso cercano), entonces eso lleva a un intercambio, lo cual es terrible para el rendimiento.
Rick James
7

Su título pregunta sobre innodb_buffer_pool_size, pero sospecho que ese no es el verdadero problema. (Rolando comentó por qué lo ha configurado lo suficientemente grande, incluso demasiado grande).

He establecido conexiones máximas = 800 que a veces saturan y muelen el servidor para detenerlo.

Eso no está claro. 800 usuarios en modo "Suspender" tienen prácticamente cero impacto en el sistema. 800 hilos activos serían un desastre. ¿Cuántos hilos se están "ejecutando"?

¿Se están bloqueando los hilos entre sí? Ver SHOW ENGINE INNODB STATUS para obtener algunas pistas sobre puntos muertos, etc.

¿Aparecen consultas en el registro lento? Optimicémoslos.

Qué versión estás usando? XtraDB (un reemplazo directo para InnoDB) hace un mejor trabajo al usar múltiples núcleos. 5.6.7 hace un trabajo aún mejor.

innodb_buffer_pool_instances: cambie esto a 8 (suponiendo un 20G buffer_pool); reducirá ligeramente la contención de Mutex.

¿Está vinculado a E / S o está vinculado a la CPU? Las soluciones son radicalmente diferentes, dependiendo de su respuesta.

SSD: podría ser mejor si todos los archivos de registro estuvieran en unidades que no sean SSD.

Rick James
fuente
6

Más memoria siempre es mejor, pero en mi experiencia la mayoría de las veces el tamaño de la agrupación de almacenamiento intermedio no debería ajustarse al tamaño de sus datos. Muchas tablas están inactivas la mayoría de las veces, como las tablas de respaldo, por lo que el tamaño del grupo de búferes innodb debería ajustarse al tamaño de datos activo.

El período de tiempo que especifique para las páginas activas influye en el rendimiento, pero hay un punto óptimo, donde no obtendrá ese mayor rendimiento para un tamaño de búfer más grande. Podrías estimar / calcular / medir eso porshow engine innodb status

usuario77376
fuente