Quelle doit être la taille de mysql innodb_buffer_pool_size?

170

J'ai une base de données occupée avec uniquement des tables InnoDB d'une taille d'environ 5 Go. La base de données s'exécute sur un serveur Debian utilisant des disques SSD et j'ai défini le nombre maximal de connexions = 800, qui saturent parfois le serveur et l'empêchent de s'arrêter. La requête moyenne par seconde est d'environ 2,5K. J'ai donc besoin d'optimiser l'utilisation de la mémoire pour faire de la place pour un maximum de connexions possibles.

J'ai déjà vu des suggestions selon lesquelles innodb_buffer_pool_size devrait représenter jusqu'à 80% de la mémoire totale. Par contre, je reçois cet avertissement du 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

Voici mes variables innodb actuelles:

| 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                                                                                                                      |

Remarque secondaire qui pourrait être pertinente: je vois que lorsque j'essaie d'insérer un article volumineux (disons plus de 10 Ko) de Drupal (installé sur un serveur Web distinct) dans la base de données, il dure indéfiniment et la page ne s'affiche pas correctement.

À ce propos, je me demande quelle devrait être mon innodb_buffer_pool_size pour des performances optimales. J'apprécie vos suggestions pour définir ceci et d'autres paramètres de manière optimale pour ce scénario.

alfish
la source

Réponses:

252

Votre innodb_buffer_pool_size est énorme. Vous l'avez réglé à 20971520000. C'est 19,5135 Go. Si vous ne disposez que de 5 Go de données et d'index InnoDB, vous ne devriez avoir qu'environ 8 Go. Même cela peut être trop élevé.

Voici ce que vous devriez faire. D'abord exécuter cette requête

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;

Cela vous donnera le RIBPS, taille recommandée du pool de mémoire tampon InnoDB, basé sur toutes les données et index InnoDB, avec 60% supplémentaires.

Par exemple

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>

Avec cette sortie, vous définissez ce qui suit dans /etc/my.cnf

[mysqld]
innodb_buffer_pool_size=8G

Prochain, service mysql restart

Après le redémarrage, exécutez mysql pendant une semaine ou deux. Ensuite, lancez cette requête:

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;

Cela vous indiquera combien de Go de mémoire réellement utilisés par InnoDB Data dans le pool de mémoire tampon InnoDB en ce moment.

J'ai déjà écrit à ce sujet auparavant: que définir innodb_buffer_pool et pourquoi ..?

Vous pouvez simplement exécuter cette DataGBrequête maintenant plutôt que de reconfigurer, de redémarrer et d’attendre une semaine.

Cette valeur DataGBressemble plus étroitement à la taille du pool de mémoire tampon InnoDB + (pourcentage spécifié dans innodb_change_buffer_max_size). Je suis sûr que ce sera beaucoup moins que les 20000M que vous avez réservés en ce moment. Les économies en RAM peuvent être utilisées pour régler d’autres choses comme

CAVEAT # 1

Il est très important de noter que parfois, InnoDB peut nécessiter 10% de plus que la valeur de innodb_buffer_pool_size . Voici ce que dit la documentation MySQL à ce sujet:

Plus cette valeur est grande, moins il faut d'E / S de disque pour accéder aux données des tables. Sur un serveur de base de données dédié, vous pouvez définir jusqu'à 80% de la taille de la mémoire physique de la machine. Préparez-vous à réduire cette valeur si ces autres problèmes se produisent:

La compétition pour la mémoire physique peut provoquer une pagination dans le système d'exploitation.

InnoDB réserve de la mémoire supplémentaire pour les tampons et les structures de contrôle, de sorte que l'espace total alloué est supérieur d'environ 10% à la taille spécifiée.

L'espace d'adressage doit être contigu, ce qui peut poser problème sur les systèmes Windows dotés de DLL chargées à des adresses spécifiques.

Le temps nécessaire pour initialiser le pool de mémoire tampon est approximativement proportionnel à sa taille. Sur les grandes installations, ce temps d’initialisation peut être important. Par exemple, sur un serveur Linux x86_64 moderne, l'initialisation d'un pool de mémoire tampon de 10 Go prend environ 6 secondes. Voir Section 8.9.1, «Le pool de mémoire tampon InnoDB» .

CAVEAT # 2

Je vois les valeurs suivantes dans votre my.cnf

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

Ce nombre empêchera InnoDB d’accéder à plusieurs cœurs.

Veuillez définir les éléments suivants:

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

J'ai déjà écrit à ce sujet dans DBA StackExchange

Je viens de répondre à une question comme celle-ci dans ServerFault en utilisant une formule plus concise :

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
la source
1
Merci pour ce super post! Votre formule commençant par commence à SELECT (PagesData*PageSize)/POWER(1024,3) DataGB FROM...générer l'erreur suivante sur MySQL 5.7: " La fonctionnalité 'INFORMATION_SCHEMA.GLOBAL_STATUS' est désactivée. Reportez-vous à la documentation pour 'show_compatibility_56' ". Auriez-vous une version mise à jour par hasard?
Benjamin
Je reçois 307 RIBPS et 264G. Cela signifie que j'ai besoin de 307 Go de RAM?
E_Blue
Plus comme 264G. Mais vous devriez avoir assez de RAM pour cela, sinon donnez les 80% mentionnés ci-dessus à mysql, en fonction de ce qui tourne sur le système.
Sjas
2
Le plus grand post que j'ai jamais lu! J'ai une ~ grosse base de données autour de 3 Go. Après avoir lu votre réponse / article, la vitesse des liens a été
multipliée par deux
4
@Benjamin: Depuis MySQL 5.7.6, le programme information_schema est fusionné dans le programme performance_schema. Il suffit donc de remplacer "information_schema" par "performance_schema" dans la requête pour que cela fonctionne. Source: dev.mysql.com/doc/refman/5.7/fr/status-table.html
Ralph Bolton
11

Quelque chose comme ça? Utiliser SHOW VARIABLESet SHOW GLOBAL STATUS:

Expression: innodb_buffer_pool_size / _ram
Signification: % de la RAM utilisée pour InnoDB buffer_pool
Plage recommandée: 60 ~ 80%

Expression: Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests
Signification: Les demandes de lecture qui devaient frapper le disque
Plage recommandée: 0-2%
Que faire si hors limites: Augmentez innodb_buffer_pool_size si vous en avez assez RAM.

Expression: Innodb_pages_read / Innodb_buffer_pool_read_requests
Signification: Lire les demandes qui devaient frapper le disque.
Plage recommandée: 0-2%
Que faire si hors limites: Augmentez innodb_buffer_pool_size si vous avez assez de RAM.

Expression: Innodb_pages_written / Innodb_buffer_pool_write_requests
Signification: écrire des demandes qui devaient frapper le disque.
Plage recommandée: 0-15%
Que faire si hors limites: Vérifiez innodb_buffer_pool_size

Expression: Innodb_buffer_pool_reads / Uptime
Signification: Lit
Plage recommandée: 0-100 / sec.
Que faire si hors limites: Augmentez innodb_buffer_pool_size?

Expression: (Innodb_buffer_pool_reads + Innodb_buffer_pool_pages_flushed) / Uptime
Signification: InnoDB I / O
Plage recommandée: 0-100 / sec.
Que faire si hors limites: Augmentez innodb_buffer_pool_size?

Expression: Innodb_buffer_pool_pages_flushed / Uptime
Signification: écrit (
plage ) Plage recommandée: 0-100 / sec.
Que faire si hors limites: Augmentez innodb_buffer_pool_size?

Expression: Innodb_buffer_pool_wait_free / Uptime
Signification: Compteur pour l'absence de pages libres dans buffer_pool. C'est-à-dire que toutes les pages sont sales.
Plage recommandée: 0-1 / sec.
Que faire si hors limites: Assurez-vous d'abord que innodb_buffer_pool_size est définie de manière raisonnable; si le problème persiste, diminuez innodb_max_dirty_pages_pct

Rick James
la source
Merci @Rick pour le gentil commentaire. Quelle innodb_buffer_pool_sizevaleur spécifie? Taille réelle ou configurée?
Joker
1
@joker - innodb_buffer_pool_sizeindique la taille maximale. Sur un serveur typique, le "pool de tampons" commence petit, mais augmente rapidement pour atteindre cette taille maximale et y reste. Remarque: Si la taille de celle-ci est supérieure à la RAM (ou même proche), cela conduit à un échange, ce qui est terrible pour les performances.
Rick James
7

Votre titre demande à propos de innodb_buffer_pool_size, mais je suppose que ce n’est pas le vrai problème. (Rolando a expliqué pourquoi vous l'aviez défini assez grand, voire trop grand.)

J'ai défini le nombre maximal de connexions = 800, qui saturent parfois le serveur et l’arrêtent.

Ce n'est pas clair. 800 utilisateurs en mode "Veille" n'a pratiquement aucun impact sur le système. 800 threads actifs seraient un désastre. Combien de threads sont "en cours d'exécution"?

Est-ce que les fils se bloquent? Voir SHOW ENGINE INNODB STATUS pour quelques indices sur les blocages, etc.

Des requêtes apparaissent-elles dans le slowlog? Optimisons-les.

Quelle version utilisez-vous? XtraDB (un remplacement immédiat pour InnoDB) utilise mieux les cœurs multiples. 5.6.7 fait un travail encore meilleur.

innodb_buffer_pool_instances - changez-le en 8 (en supposant un 20G buffer_pool); cela réduira légèrement le conflit de Mutex.

Êtes-vous lié I / O ou êtes-vous lié au CPU? Les solutions sont radicalement différentes, en fonction de votre réponse.

SSD - Il serait peut-être préférable que tous les fichiers journaux se trouvent sur des lecteurs non-SSD.

Rick James
la source
6

Il est toujours préférable d'avoir plus de mémoire, mais d'après mon expérience, la plupart du temps, la taille du pool de mémoire tampon ne doit pas correspondre à la taille de vos données. La plupart du temps, de nombreuses tables sont inactives, comme les tables de sauvegarde, la taille du pool de mémoire tampon innodb doit donc correspondre à la taille de vos données actives.

Le délai que vous spécifiez pour les pages actives influe sur les performances, mais il existe un point optimal, où vous n'obtiendrez pas autant de performances pour une taille de mémoire tampon plus grande. Vous pouvez estimer / calculer / mesurer cela enshow engine innodb status

utilisateur77376
la source