web-dev-qa-db-fra.com

Comment résoudre l'avertissement mysql: "InnoDB: page_cleaner: la boucle prévue de 1000 ms a pris XXX ms. Les paramètres risquent de ne pas être optimaux"?

J'ai couru un mysql importer mysql dummyctrad <dumpfile.sql sur le serveur et cela prend trop de temps pour terminer. Le fichier de vidage est d'environ 5G. Le serveur est un Centos 6, mémoire = 16G et 8cores, mysql v 5.7 x64-

Ces messages/statuts normaux sont-ils "en attente de vidage de table" et le message InnoDB: page_cleaner: 1000ms intended loop took 4013ms. The settings might not be optimal

contenu du journal mysql

2016-12-13T10:51:39.909382Z 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 4013ms. The settings might not be optimal. (flushed=1438 and evicted=0, during the time.)
2016-12-13T10:53:01.170388Z 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 4055ms. The settings might not be optimal. (flushed=1412 and evicted=0, during the time.)
2016-12-13T11:07:11.728812Z 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 4008ms. The settings might not be optimal. (flushed=1414 and evicted=0, during the time.)
2016-12-13T11:39:54.257618Z 3274915 [Note] Aborted connection 3274915 to db: 'dummyctrad' user: 'root' Host: 'localhost' (Got an error writing communication packets)

Liste des processus:

mysql> show processlist \G;
*************************** 1. row ***************************
     Id: 3273081
   User: root
   Host: localhost
     db: dummyctrad
Command: Field List
   Time: 7580
  State: Waiting for table flush
   Info: 
*************************** 2. row ***************************
     Id: 3274915
   User: root
   Host: localhost
     db: dummyctrad
Command: Query
   Time: 2
  State: update
   Info: INSERT INTO `radacct` VALUES (351318325,'kxid ge:7186','abcxyz5976c','user100
*************************** 3. row ***************************
     Id: 3291591
   User: root
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: starting
   Info: show processlist
*************************** 4. row ***************************
     Id: 3291657
   User: remoteuser
   Host: portal.example.com:32800
     db: ctradius
Command: Sleep
   Time: 2
  State: 
   Info: NULL
4 rows in set (0.00 sec)

Update-1

mysqlforum , innodb_lru_scan_depth

la modification de la valeur innodb_lru_scan_depth en 256 a amélioré le temps d’exécution des requêtes d’insertion + aucun message d’avertissement dans le journal; la valeur par défaut était innodb_lru_scan_depth = 1024;

SET GLOBAL innodb_lru_scan_depth=256;

39
satch_boogie

InnoDB: page_cleaner: la boucle prévue de 1000 ms prenait 4013ms. Les paramètres peuvent ne pas être optimaux. (rincé = 1438 et expulsé = 0, pendant le temps.)

Le problème est typique d’une instance MySQL où le taux de modifications de la base de données est élevé. En exécutant votre importation de 5 Go, vous créez rapidement des pages non conformes. Au fur et à mesure que les pages endommagées sont créées, le fil de nettoyage de page est chargé de copier les pages endommagées de la mémoire sur le disque.

Dans votre cas, je suppose que vous n’effectuez pas d’importations de 5 Go à tout moment. Il s’agit donc d’un taux de chargement de données exceptionnellement élevé et temporaire. Vous pouvez probablement ignorer les avertissements, car InnoDB va progressivement se rattraper.


Voici une explication détaillée des internes menant à cet avertissement.

Une fois par seconde, le nettoyeur de page analyse le pool de mémoire tampon afin de rechercher les pages modifiées à vider du pool de mémoire tampon vers le disque. L’avertissement que vous avez vu montre qu’il a beaucoup de pages encrassées à vider et qu’il faut plus de 4 secondes pour vider un lot d’entre elles sur disque, alors que le travail devrait être terminé en moins d’une seconde. En d'autres termes, il mord plus qu'il ne peut mâcher.

Vous avez ajusté cette valeur en réduisant innodb_lru_scan_depth de 1024 à 256. Cela réduit la distance dans la réserve de tampons utilisée par le processus de nettoyage de page pour rechercher les pages modifiées au cours de son cycle d'une fois par seconde. Vous lui demandez de prendre de plus petites bouchées.

Notez que si vous avez plusieurs instances de pool de mémoire tampon, le vidage demandera plus de travail. Il mord innodb_lru_scan_depth quantité de travail pour chaque instance de pool de mémoire tampon. Vous avez donc peut-être causé par inadvertance ce goulot d'étranglement en augmentant le nombre de pools de mémoire tampon sans réduire la profondeur d'analyse.

La documentation de innodb_lru_scan_depth indique: "Un paramètre inférieur à la valeur par défaut convient généralement à la plupart des charges de travail." On dirait qu'ils ont attribué à cette option une valeur trop élevée par défaut.

Vous pouvez limiter les IOPS utilisées par le vidage d'arrière-plan, avec les options innodb_io_capacity et innodb_io_capacity_max. La première option est une limite souple du débit d'E/S que InnoDB demandera. Mais cette limite est flexible; Si le vidage est en retard sur le taux de création de nouvelles pages sales, InnoDB augmentera dynamiquement le taux de vidage au-delà de cette limite. La deuxième option définit une limite plus stricte sur la mesure dans laquelle InnoDB pourrait augmenter le taux de rinçage.

Si le taux de vidage peut suivre le taux moyen de création de nouvelles pages non conformes, tout ira bien. Toutefois, si vous créez systématiquement des pages non conformes plus rapidement que possible, votre pool de tampons se remplira de pages non modifiées jusqu'à ce que celles-ci dépassent innodb_max_dirty_page_pct du pool de tampons. À ce stade, le taux de vidage augmente automatiquement et le message page_cleaner peut à nouveau envoyer des avertissements.

Une autre solution serait de mettre MySQL sur un serveur avec des disques plus rapides. Vous avez besoin d'un système d'E/S capable de gérer le débit demandé par le vidage de votre page.

Si vous voyez tout le temps cet avertissement sous un trafic moyen, vous essayez peut-être de faire trop de requêtes d'écriture sur ce serveur MySQL. Il est peut-être temps de passer à la vitesse supérieure et de scinder les écritures sur plusieurs instances MySQL, chacune avec son propre système de disque.

En savoir plus sur le nettoyeur de pages:

61
Bill Karwin

Le goulot d'étranglement est l'enregistrement des données sur le disque dur. Quel que soit votre disque dur: SSD, normal, NVMe, etc.

Notez que cette solution s'applique principalement à InnoDB

J'ai eu le même problème, j'ai appliqué peu de solutions.

1er: vérifier ce qui ne va pas

atop -d vous montrera l'utilisation du disque. Si le disque est "occupé", essayez alors d'arrêter toutes les requêtes sur la base de données (mais n'arrêtez pas le service du serveur mysql!)

Pour contrôler le nombre de requêtes que vous avez, utilisez mytop, innotop ou équivalent.

Si vous avez 0 requêtes, mais que l'utilisation du disque est ENCORE proche de 100% à partir de quelques secondes/quelques minutes, cela signifie que le serveur mysql essaie de vider les pages sales/effectue un nettoyage comme mentionné précédemment (excellent post de Bill Karwin) .

ALORS vous pouvez essayer d’appliquer de telles solutions:

2e: optimisation du matériel informatique

Si votre matrice n'est pas en RAID 1 + 0, envisagez de doubler la vitesse de sauvegarde des données avec ce type de solution. Essayez d'étendre les possibilités de votre lecteur de disque dur avec l'écriture de données. Essayez d’utiliser un disque dur SSD ou plus rapide. L’application de cette résolution dépend de vos possibilités matérielles et budgétaires et peut varier.

3ème: réglage du logiciel

Si harware cotroller fonctionne bien, mais que vous souhaitez augmenter la vitesse de sauvegarde des données, vous pouvez le configurer dans le fichier de configuration mysql:

3.1.

innodb_flush_log_at_trx_commit = 2 -> si vous utilisez des tables innodb Cela fonctionne le mieux avec une table par fichier: innodb_file_per_table = 1

3.2.

continuer avec InnoDB: innodb_flush_method = O_DIRECT innodb_doublewrite = 0 innodb_support_xa = 0 innodb_checksums = 0

Les lignes ci-dessus réduisent en général la quantité de données à enregistrer sur le disque dur, ce qui améliore les performances.

3.3

general_log = 0 slow_query_log = 0

Les lignes ci-dessus désactivent l’enregistrement des journaux; bien sûr, c’est une autre quantité de données à enregistrer sur le disque dur.

3.4 vérifiez à nouveau ce qui se passe, par exemple tail -f /var/log/mysql/error.log

4ème: notes générales

Notes générales: Ceci a été testé sous MySQL 5.6 ET 5.7.22 OS: Debian 9 RAID: 1 + 0 disques SSD Base de données: tables InnoDB innodb_buffer_pool_size = 120G innodb_buffer_pool_instances = 8 innodb_read_io_threads = 64 innodb_write_io_threads = 64 Quantité totale de RAM sur le serveur: 200 Go

Après cela, vous constaterez peut-être une utilisation accrue du processeur. c'est normal, car l'écriture de données est plus rapide, donc le processeur travaillera plus fort.

Si vous utilisez my.cnf, n'oubliez pas de redémarrer le serveur MySQL.

5ème: supplément

En étant intrigué, j'ai fait cette bizarrerie avec SET GLOBAL innodb_lru_scan_depth=256; mentionné ci-dessus.

En travaillant avec de grandes tables, je n’ai constaté aucun changement dans les performances.

Après les corrections ci-dessus, je ne me suis pas débarrassé des avertissements, mais tout le système fonctionne beaucoup plus rapidement. Tout ce qui précède n’est qu’une expérimentation, mais j’ai mesuré les résultats, cela m’a un peu aidé, alors espérons que cela pourra être utile à d’autres.

11
Vilq