Quanto dovrebbe essere grande mysql innodb_buffer_pool_size?


170

Ho un database occupato con solo tabelle InnoDB che ha una dimensione di circa 5 GB. Il database gira su un server Debian usando dischi SSD e ho impostato un numero massimo di connessioni = 800 che a volte saturano e fermano il server. La query media al secondo è di circa 2,5 K. Quindi ho bisogno di ottimizzare l'utilizzo della memoria per fare spazio alle massime connessioni possibili.

Ho visto dei suggerimenti secondo cui innodb_buffer_pool_size dovrebbe essere fino a% 80 della memoria totale. D'altra parte ricevo questo avviso dallo 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

Ecco le mie attuali variabili innodb:

| 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 a margine che potrebbe essere rilevante: vedo che quando provo a inserire un post di grandi dimensioni (diciamo oltre 10 KB) da Drupal (che si trova su un server web separato) nel database, dura per sempre e la pagina non ritorna correttamente.

Per quanto riguarda questi, mi chiedo quale dovrebbe essere il mio innodb_buffer_pool_size per prestazioni ottimali. Apprezzo i tuoi suggerimenti per impostare questo e altri parametri in modo ottimale per questo scenario.

Risposte:


252

Il tuo innodb_buffer_pool_size è enorme. L'hai impostato su 20971520000. Sono 19.5135 GB. Se hai solo 5 GB di dati e indici InnoDB, dovresti avere solo circa 8 GB. Anche questo potrebbe essere troppo alto.

Ecco cosa dovresti fare. Per prima cosa esegui questa query

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;

Questo ti darà le RIBPS, le dimensioni consigliate del pool di buffer InnoDB basate su tutti i dati e gli indici InnoDB con un ulteriore 60%.

Per esempio

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 questo output, dovresti impostare quanto segue in /etc/my.cnf

[mysqld]
innodb_buffer_pool_size=8G

Il prossimo, service mysql restart

Dopo il riavvio, esegui mysql per una settimana o due. Quindi, esegui questa query:

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;

Questo ti fornirà quanti GB effettivi di memoria sono attualmente utilizzati dai dati InnoDB nel pool di buffer InnoDB in questo momento.

Ne ho già parlato prima: cosa impostare innodb_buffer_pool e perché ..?

Puoi semplicemente eseguire questa DataGBquery in questo momento piuttosto che riconfigurare, riavviare e attendere una settimana.

Questo valore DataGBricorda più da vicino quanto deve essere grande il pool di buffer InnoDB + (percentuale specificata in innodb_change_buffer_max_size). Sono sicuro che questo sarà molto inferiore ai 20000M che hai prenotato in questo momento. I risparmi nella RAM possono essere utilizzati per ottimizzare altre cose come

CAVEAT # 1

Questo è molto importante da notare: a volte, InnoDB potrebbe richiedere un ulteriore 10% sul valore per innodb_buffer_pool_size . Ecco cosa dice la documentazione MySQL su questo:

Più grande si imposta questo valore, meno I / O su disco è necessario per accedere ai dati nelle tabelle. Su un server di database dedicato, è possibile impostare fino all'80% della dimensione della memoria fisica della macchina. Preparati a ridimensionare questo valore se si verificano questi altri problemi:

La competizione per la memoria fisica potrebbe causare il paging nel sistema operativo.

InnoDB riserva memoria aggiuntiva per buffer e strutture di controllo, in modo che lo spazio allocato totale sia circa il 10% maggiore della dimensione specificata.

Lo spazio degli indirizzi deve essere contiguo, il che può costituire un problema sui sistemi Windows con DLL che si caricano su indirizzi specifici.

Il tempo per inizializzare il pool di buffer è approssimativamente proporzionale alla sua dimensione. In installazioni di grandi dimensioni, questo tempo di inizializzazione può essere significativo. Ad esempio, su un moderno server Linux x86_64, l'inizializzazione di un pool buffer da 10 GB richiede circa 6 secondi. Vedere la Sezione 8.9.1, "Il pool di buffer InnoDB" .

CAVEAT # 2

Vedo i seguenti valori nel tuo my.cnf

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

Questo numero impedisce a InnoDB di accedere a più core

Si prega di impostare quanto segue:

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

Ne ho già parlato in precedenza in StackExchange DBA

Ho appena risposto a una domanda come questa in ServerFault usando una formula più 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;

1
Grazie per questo bellissimo post! La tua formula che inizia con SELECT (PagesData*PageSize)/POWER(1024,3) DataGB FROM...genera il seguente errore su MySQL 5.7: " La funzione 'INFORMATION_SCHEMA.GLOBAL_STATUS' è disabilitata; vedi la documentazione per 'show_compatibility_56' ". Avresti una versione aggiornata per caso?
Benjamin,

Ottengo 307 RIBPS e 264G. Questo significa che ho bisogno di 307 GB di RAM?
E_Blue,

Più come 264G. Ma dovresti avere abbastanza RAM per quello, altrimenti dai l'80% della tua RAM a mysql, a seconda di cos'altro funziona sul sistema.
sjas,

2
Il miglior post che abbia mai letto! Ho un ~ grande database di circa 3 GB. Dopo aver letto la tua risposta / articolo e la velocità dei collegamenti è salita a 2x
fat_mike il

4
@Benjamin: da MySQL 5.7.6 information_schema viene unito in performance_schema. Quindi basta cambiare "information_schema" in "performance_schema" nella query per farlo funzionare. Fonte: dev.mysql.com/doc/refman/5.7/en/status-table.html
Ralph Bolton

11

Qualcosa come questo? Utilizzando SHOW VARIABLESe SHOW GLOBAL STATUS:

Espressione: innodb_buffer_pool_size / _ram
Significato: % di RAM utilizzata per InnoDB buffer_pool
Intervallo consigliato: 60 ~ 80%

Espressione: Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests
Significato: Leggi le richieste che hanno dovuto colpire il disco
Intervallo consigliato: 0-2%
Cosa fare se non compreso nell'intervallo: Aumentare innodb_buffer_pool_size se ne hai abbastanza RAM.

Espressione: Innodb_pages_read / Innodb_buffer_pool_read_requests
Significato: richieste di lettura che devono colpire il disco
Intervallo consigliato: 0-2%
Cosa fare se non compreso nell'intervallo: Aumentare innodb_buffer_pool_size se si dispone di RAM sufficiente.

Espressione: Innodb_pages_written / Innodb_buffer_pool_write_requests
Significato: scrivere le richieste che devono colpire il disco
Intervallo consigliato: 0-15%
Cosa fare se non compreso nell'intervallo: Check innodb_buffer_pool_size

Espressione: Innodb_buffer_pool_reads / Uptime
Significato: Legge
Intervallo consigliato: 0-100 / sec.
Cosa fare se non compreso nell'intervallo: aumentare innodb_buffer_pool_size?

Espressione: (Innodb_buffer_pool_reads + Innodb_buffer_pool_pages_flushed) / Uptime
Significato: I / O InnoDB
Intervallo consigliato: 0-100 / sec.
Cosa fare se non compreso nell'intervallo: aumentare innodb_buffer_pool_size?

Espressione: Innodb_buffer_pool_pages_flushed / Uptime
Significato: Scrive (arrossisce)
Intervallo raccomandato: 0-100 / sec.
Cosa fare se non compreso nell'intervallo: aumentare innodb_buffer_pool_size?

Espressione: Innodb_buffer_pool_wait_free / Uptime
Significato: contatore per quando non ci sono pagine libere in buffer_pool. Cioè, tutte le pagine sono sporche.
Intervallo raccomandato: 0-1 / sec.
Cosa fare se non rientra nell'intervallo: assicurarsi innanzitutto che innodb_buffer_pool_size sia impostato in modo ragionevole; se il problema persiste, ridurre innodb_max_dirty_pages_pct


Grazie @Rick per il bel commento. Quale innodb_buffer_pool_sizevalore specifica? Dimensione effettiva o configurata?
Joker il

1
@joker: innodb_buffer_pool_sizeindica la dimensione massima. In un tipico server, il "pool buffer" inizia in piccolo, ma cresce rapidamente fino a quella dimensione massima e rimane lì. Nota: se è più grande della RAM (o anche vicino), ciò porta allo scambio, il che è terribile per le prestazioni.
Rick James,

7

Il tuo titolo chiede innodb_buffer_pool_size, ma sospetto che non sia il vero problema. (Rolando ha commentato perché l'hai impostato abbastanza grande, anche troppo grande.)

Ho impostato un numero massimo di connessioni = 800 che a volte saturano e fermano il server.

Non è chiaro. 800 utenti in modalità "Sleep" hanno un impatto praticamente nullo sul sistema. 800 thread attivi sarebbero un disastro. Quanti thread sono "in esecuzione"?

I thread si stanno bloccando a vicenda? Vedi SHOW ENGINE INNODB STATUS per alcuni indizi su deadlock, ecc.

Ci sono delle domande che appaiono nel slowlog? Ottimizziamoli.

Quale versione stai usando? XtraDB (un sostituto drop-in per InnoDB) fa un lavoro migliore nell'uso di più core. 5.6.7 fa un lavoro ancora migliore.

innodb_buffer_pool_instances: modificalo in 8 (supponendo un buffer_pool 20G); si ridurrà leggermente sulla contesa Mutex.

Siete collegati in I / O o in CPU? Le soluzioni sono radicalmente diverse, a seconda della risposta.

SSD - Potrebbe essere meglio se tutti i file di registro fossero su unità non SSD.


6

Più memoria è sempre migliore, ma nella mia esperienza la maggior parte delle volte la dimensione del pool di buffer non dovrebbe adattarsi alla dimensione dei dati. Molte tabelle sono inattive il più delle volte, come le tabelle di backup in giro, quindi la dimensione del pool buffer innodb dovrebbe adattarsi alle dimensioni dei dati attivi.

L'intervallo di tempo specificato per le pagine attive influenza le prestazioni, ma esiste un punto ottimale, in cui non si otterranno prestazioni superiori per dimensioni del buffer maggiori. È possibile stimare / calcolare / misurare che entroshow engine innodb status

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.