J'ai une base de données occupée avec uniquement des tables InnoDB qui fait environ 5 Go. La base de données fonctionne sur un serveur Debian à l'aide de disques SSD et j'ai défini le nombre maximal de connexions = 800, ce qui parfois sature et arrête le serveur. La requête moyenne par seconde est d'environ 2,5 Ko. 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 vu des suggestions selon lesquelles innodb_buffer_pool_size devrait représenter jusqu'à% 80 de la mémoire totale. D'un autre côté, 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 |
Une note latérale qui pourrait être pertinente: je vois que lorsque j'essaie d'insérer un grand message (disons plus de 10 Ko) de Drupal (qui se trouve sur un serveur Web séparé) dans la base de données, cela dure éternellement et la page ne revient pas correctement.
À ce sujet, je me demande quelle devrait être ma taille innodb_buffer_pool_size pour des performances optimales. J'apprécie vos suggestions pour définir ce paramètre et d'autres de manière optimale pour ce scénario.
Votre innodb_buffer_pool_size est énorme. Vous l'avez défini sur 20971520000
. C'est 19,5135 Go. Si vous ne disposez que de 5 Go de données et d'index InnoDB, vous ne devriez disposer que d'environ 8 Go. Même cela peut être trop élevé.
Voici ce que vous devriez faire. Exécutez d'abord 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 de pool de mémoire tampon InnoDB recommandée, basée 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éfiniriez ce qui suit dans /etc/my.cnf
[mysqld]
innodb_buffer_pool_size=8G
Suivant, service mysql restart
Après le redémarrage, exécutez MySQL pendant une semaine ou deux. Ensuite, exécutez 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 donnera combien de Go de mémoire réels sont actuellement utilisés par InnoDB Data dans le pool de tampons InnoDB.
J'ai déjà écrit à ce sujet: Que définir innodb_buffer_pool et pourquoi ..?
Vous pouvez simplement exécuter cette requête DataGB
maintenant plutôt que de reconfigurer, redémarrer et attendre une semaine.
Cette valeur DataGB
ressemble plus à la taille du pool de tampons InnoDB + (pourcentage spécifié dans innodb_change_buffer_max_size). Je suis sûr que ce sera bien moins que le 20000M que vous avez réservé en ce moment. Les économies de RAM peuvent être utilisées pour régler d'autres choses comme
Ceci est très important à noter: Parfois, InnoDB peut nécessiter 10% supplémentaires par rapport à la valeur pour innodb_buffer_pool_size . Voici ce que la MySQL Documentation dit à ce sujet:
Plus vous définissez cette valeur, moins d'E/S de disque sont nécessaires pour accéder aux données des tables. Sur un serveur de base de données dédié, vous pouvez définir cela jusqu'à 80% de la taille de la mémoire physique de la machine. Soyez prêt à réduire cette valeur si ces autres problèmes se produisent:
La concurrence pour la mémoire physique peut entraîner la 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é soit environ 10% supérieur à la taille spécifiée.
L'espace d'adressage doit être contigu, ce qui peut être un problème sur les systèmes Windows avec des DLL qui se chargent à des adresses spécifiques.
Le temps d'initialisation du pool de tampons est à peu près 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 tampons InnoDB" .
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 le DBA StackExchange
Je viens de répondre à une question comme celle-ci dans Server Fault 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;
Quelque chose comme ça? En utilisant SHOW VARIABLES
et SHOW GLOBAL STATUS
:
Expression: innodb_buffer_pool_size / _ram
Sens: % de RAM utilisée pour InnoDB buffer_pool
Gamme recommandée: 60 ~ 80%
Expression: Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests
Sens: Lire les demandes qui devaient frapper le disque
Gamme recommandée: 0-2%
Que faire si hors de portée: Augmentez innodb_buffer_pool_size si vous avez suffisamment de RAM.
Expression: Innodb_pages_read / Innodb_buffer_pool_read_requests
Sens: Lire les demandes qui devaient frapper le disque
Gamme recommandée: 0-2%
Que faire si hors de portée: Augmentez innodb_buffer_pool_size si vous avez suffisamment de RAM.
Expression: Innodb_pages_written / Innodb_buffer_pool_write_requests
Sens: Écrire des demandes qui devaient frapper le disque
Gamme recommandée: 0-15%
Que faire si hors de portée: Vérifiez innodb_buffer_pool_size
Expression: Innodb_buffer_pool_reads / Uptime
Sens: Lit
Gamme recommandée: 0-100/sec.
Que faire si hors de portée: Augmentez innodb_buffer_pool_size?
Expression: (Innodb_buffer_pool_reads + Innodb_buffer_pool_pages_flushed) / Uptime
Sens: E/S InnoDB
Gamme recommandée: 0-100/sec.
Que faire si hors de portée: Augmentez innodb_buffer_pool_size?
Expression: Innodb_buffer_pool_pages_flushed / Uptime
Sens: Écrit (rince)
Gamme recommandée: 0-100/sec.
Que faire si hors de portée: Augmentez innodb_buffer_pool_size?
Expression: Innodb_buffer_pool_wait_free / Uptime
Sens: Contre quand il n'y a pas de pages libres dans buffer_pool. Autrement dit, toutes les pages sont sales.
Gamme recommandée: 0-1/sec.
Que faire si hors de portée: Assurez-vous d'abord que innodb_buffer_pool_size est défini de manière raisonnable; si le problème persiste, diminuez innodb_max_dirty_pages_pct
Votre titre pose des questions sur innodb_buffer_pool_size, mais je soupçonne que ce n'est pas le vrai problème. (Rolando a expliqué pourquoi vous l'aviez réglé assez grand, voire trop grand.)
J'ai défini le nombre maximal de connexions = 800, ce qui sature parfois et arrête le serveur.
Ce n'est pas clair. 800 utilisateurs en mode "Veille" n'ont pratiquement aucun impact sur le système. 800 threads actifs seraient un désastre. Combien de threads "sont en cours d'exécution"?
Les fils se bloquent-ils? Voir SHOW ENGINE INNODB STATUS pour des indices sur les blocages, etc.
Des requêtes apparaissent-elles dans le slowlog? Optimisons-les.
Quelle version utilisez-vous? XtraDB (un remplacement direct pour InnoDB) fait un meilleur travail en utilisant plusieurs cœurs. 5.6.7 fait un travail encore meilleur.
innodb_buffer_pool_instances - changez ceci en 8 (en supposant un buffer_pool 20G); cela réduira légèrement le conflit Mutex.
Êtes-vous lié aux E/S ou lié au processeur? Les solutions sont radicalement différentes, selon votre réponse.
SSD - Il serait préférable que tous les fichiers journaux se trouvent sur des disques non SSD.
Plus de mémoire est toujours mieux, 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. De nombreuses tables sont inactives la plupart du temps, comme les tables de sauvegarde qui traînent, donc la taille du pool de mémoire tampon innodb devrait plutôt vous convenir à la taille des données actives.
Le délai que vous spécifiez pour les pages actives influence les performances, mais il y a un point optimal, où vous n'obtiendrez pas plus de performances pour une taille de tampon plus grande. Vous pourriez estimer/calculer/mesurer cela par show engine innodb status