Possible de faire en sorte que MySQL utilise plus d'un noyau?

131

On m'a présenté des serveurs dédiés MySQL qui n'utilisent jamais plus d'un noyau. Je suis plus développeur que DBA pour MySQL, alors besoin d'aide

Installer

Les serveurs sont assez lourds avec une charge de type OLAP / DataWarehouse (DW):

  • Primaire: 96 Go de RAM, 8 cœurs + un seul RAID 10
  • Test: 32 Go de RAM avec 4 cœurs
  • La plus grande base de données est 540 Go, le total est d'environ 1,1 To et la plupart des tables InnoDB
  • Solaris 10 Intel-64
  • MySQL 5.5.x

Remarque: La base de données la plus grande est celle qui a été répliquée à partir du serveur de reprise en ligne OLTP et le DW est chargé à partir de celui-ci. Il ne s'agit pas d'un fichier de travail complet: il ne dure que 6 à 6 semaines, il est donc plus petit que la base de données OLTP.

Observations sur un serveur de test

  • 3 connexions séparées
  • chacun a un concurrent (et différent) ALTER TABLE...DROP KEY...ADD INDEX
  • les 3 tables ont 2,5, 3,8 et 4,5 millions de lignes
  • L’utilisation du processeur atteint 25% (un cœur est épuisé) et pas plus
  • les 3 ALTER prennent 12-25 minutes (une seule sur la plus petite en prend 4,5)

Des questions

  1. Quel paramètre ou correctif est requis pour permettre à plus d'un cœur d'être utilisé?
    Pourquoi MySQL n’utilise-t-il pas tous les cœurs disponibles? (comme les autres SGBDR)
  2. Est-ce une conséquence de la réplication?

Autres notes

  • Je comprends la différence entre un "thread" SGBDR et un "thread" OS
  • Je ne parle pas de toute forme de parallélisme
  • Certaines variables système pour InnoDB et les threads sont sous-optimales
    (recherche d'un gain rapide)
  • À court terme, je ne peux pas changer la disposition du disque
  • Le système d'exploitation peut être modifié si nécessaire
  • Un seul ALTER TABLE sur la plus petite table prend 4,5 minutes (IMO choquant)

Modifier 1

  • innodb_thread_concurrency a la valeur 8 pour les deux. Oui, c'est faux, mais MySQL n'utilisera pas plusieurs cœurs.
  • innodb_buffer_pool_size est de 80 Go sur le primaire, 10 Go sur un test (une autre instance est fermée). C'est OK pour le moment.
  • innodb_file_per_table = ON

Modifier 2

Tester

  • innodb_flush_method n'affiche pas comme O_DIRECT alors qu'il devrait l'être
  • suivra les paramètres de RolandoMySQLDBA

Dites-moi si j'ai oublié quelque chose d'important

À votre santé

Mise à jour

Innodb_flush_method modifié + 3 x paramètres de thread dans la réponse de RolandoMySQLDBA
Résultat:> 1 cœur utilisé pour les tests = résultat positif

gbn
la source
@Dtest: innodb_file_per_table = ON. SHOW ENGINE INNODB STATUS \ G est-il uniquement en ligne de commande?
gbn
@Dtest: Je n'ai aucune sortie dans SQLyog et je devrais demander à quelqu'un de l'exécuter depuis la ligne de commande
gbn
1
webyog.com/forums/index.php?showtopic=1290 devrait fonctionner sans le \G. En outre, je pense SHOW INNODB STATUSest déconseillé en faveur de SHOW ENGINE INNODB STATUSdans 5.5 (je reçois une erreur en exécutant l'ancien en ligne de commande.
Derek Downey
1
Bien que toutes les autres réponses soient bonnes, étant donné que vous êtes développeur, je vous recommanderais de jeter un coup d'œil à Shard Query code.google.com/p/shard-query. Cela peut vous aider, en particulier dans un environnement de datawarehouse.
Jonathan
Merci, c'est une option à laquelle nous avons pensé. J'assume également le rôle d'administrateur de base de données.
gbn

Réponses:

123

En fait, j'ai discuté de innodb_thread_concurrency avec un expert MySQL lors de la conférence Percona Live NYC de mai 2011 .

J'ai appris quelque chose d'étonnant: malgré la documentation, il est préférable de partir innodb_thread_concurrencyà 0 (concurrence illimitée). De cette façon, InnoDB détermine le meilleur nombre d’ innodb_concurrency_ticketsouvert pour une configuration d’instance MySQL donnée.

Une fois que vous avez défini la valeur innodb_thread_concurrency0, vous pouvez définir la valeur maximale 64 ( innodb_read_io_threadset les innodb_write_io_threadsdeux depuis MySQL 5.1.38). Cela devrait impliquer davantage de cœurs.

RolandoMySQLDBA
la source
Je vais essayer ça. J'allais mettre innodb_thread_concurrency à 0 de toute façon sur la base de choses que j'ai aussi lues
gbn
9
+1 pour innodb_thread_concurrency = 0
randomx le
3
@gbn - Venant du numéro 1 de DBA.SE, un merci est un rappel de confiance et est très apprécié. Merci et de rien !!!
RolandoMySQLDBA le
set global innodb_read_io_threads = 8 Code d'erreur: 1238. La variable 'innodb_read_io_threads' est une variable en lecture seule
wgq3g23g le
2
@ wgq3g23g Si vous utilisez RDS, modifiez-le dans le groupe de paramètres DB et redémarrez l'instance. Si vous utilisez EC2 ou bare metal, ajoutez cette option à my.cnfet redémarrez mysqld. S'il vous plaît.
RolandoMySQLDBA
29

MySQL utilisera automatiquement plusieurs cœurs. Votre charge de travail est donc de 25% soit une coïncidence 1, soit d’une mauvaise configuration potentielle sous Solaris. Je ne prétends pas savoir comment régler Solaris, mais voici un article qui passe en revue certaines informations de réglage spécifiques à Solaris .

Les pages de paramétrage InnoDB ont été remaniées dans MySQL 5.5. Il contient donc quelques informations intéressantes. Des disques InnoDB conseils IO :

Si l'outil principal Unix ou le gestionnaire de tâches Windows indique que le pourcentage d'utilisation du processeur avec votre charge de travail est inférieur à 70%, votre charge de travail est probablement liée à un disque. Vous effectuez peut-être trop de validations de transaction ou le pool de mémoire tampon est trop petit. Augmenter la taille du pool de mémoire tampon peut aider, mais ne le définissez pas à plus de 80% de la mémoire physique.

Quelques autres choses à vérifier:

  • Le passage de innodb_flush_method à O_DIRECT vaut la peine d’être testé. Si cela vous aide, vous devrez peut-être monter le système de fichiers avec l' forcedirectiooption

  • Modifiez le paramètre innodb_flush_log_at_trx_commit de 1 à 0 (si vous voulez bien que vous perdiez la dernière seconde en cas de plantage de MySQL) ou 2 (si vous n’aimiez pas de perdre la dernière seconde en cas de plantage de votre système d'exploitation).

  • Vérifiez la valeur de innodb_use_sys_malloc . Cet article contient plus d'informations sur la variable.

    À ce moment-là, il n'y avait pas de bibliothèques d'allocateur de mémoire réglées pour les processeurs multicœurs. Par conséquent, InnoDB a mis en œuvre son propre allocateur de mémoire dans le sous-système mem. Cet allocateur est protégé par un seul mutex, qui peut devenir un goulot d'étranglement.

    Mais il y a quelques mises en garde à la fin de la section sur ce que signifie l'activation de la variable (elle est activée par défaut dans 5.5).

    Notez que lorsque l'allocateur de mémoire InnoDB est désactivé, InnoDB ignore la valeur du paramètre innodb_additional_mem_pool_size.

  • Il est possible que la réplication soit à l'origine du problème. Je réalise que le parallélisme ne vous intéresse pas, mais d'après la description de ce journal de travail :

    À l'heure actuelle, la réplication ne s'adapte pas correctement sur les ordinateurs multicœurs. Le seul thread esclave exécute les événements de réplication un par un et peut ne pas supporter une charge produite par plusieurs connexions client simultanées servies par la CPU du serveur maître séparé.

Au final, InnoDB pourrait ne pas être le meilleur moteur pour le stockage de données, en raison des opérations sur disque qui se produisent. Vous pouvez envisager de modifier la ou les tables de l'entrepôt de données pour qu'elles soient compressées dans MyISAM .

1 Par coïncidence, je veux dire qu’il existe un goulot d’étranglement qui empêche votre charge d’augmenter au-dessus de 25%, mais n’est pas nécessairement un problème à cœur unique forcé.

Derek Downey
la source
Merci. La section Paramètres a été ajoutée à la question. Le problème provient de plusieurs requêtes intensives utilisant un seul cœur: pas encore de paramètres de mémoire ou de thread. Plus de discussions fonctionnent toujours sur le même noyau
gbn
@gbn merci pour la mise à jour, toujours à la recherche. Je pensais que c'était une "coïncidence". Je me demande s’il s’agit d’un problème exclusivement solaire ( developers.sun.com/solaris/articles/mysql_perf_tune.html ), mais je ne connais pas grand chose à ce système.
Derek Downey
1
@Dtest: je vais également envoyer cet article à l'administrateur Solaris De bonnes choses là
gbn
1
Maintenant, la réplication est (éventuellement) multi-threadée sur l'esclave. InnoDB s'est amélioré depuis l'écriture de cette réponse. Je ne conseillerais pas d'utiliser MyISAM, surtout pas si je le compresse.
Rick James
15

Une seule connexion utilisera un seul cœur. (D'accord, InnoDB utilise d'autres threads, donc des cœurs, pour certains traitements d'E / S, mais cela n'a pas d'importance.)

Vous avez eu 3 ALTER, vous n'utilisiez donc pas plus de 3 cœurs.

Hélas, pas même PARTITION n'utilise plusieurs cœurs.

Jusqu'à récemment, le nombre maximal de connexions était atteint après 4-8 cœurs. Percona's Xtradb (inclus dans MariaDB) permet de mieux utiliser plusieurs cœurs, mais un seul par thread. Ils atteignent environ 32 cœurs.

Rick James
la source
(Mise à jour en 2015 :) Plusieurs connexions avec 5.6 maximum à environ 48 cœurs. 5.7 promet d'être encore meilleur. (C'est ce que disent les tests Oracle.) Mais toujours pas l’utilisation de plusieurs cœurs pour une seule connexion.
Rick James
Mise à jour (après avoir accédé à OpenWorld d'Oracle): la nouvelle version 8.x n'aura aucun parallélisme.
Rick James
9

IMHO et dans le cas d'utilisation décrit, vous n'utiliserez jamais plus d'un noyau. La raison en est que votre charge de travail est liée à l'IO et non à l'unité centrale. Alors que vos 3 connexions créent un nouvel index, chacune d’elles a besoin de lire la table entière à partir du disque: c’est ce qui prend du temps, pas le calcul des index.

jfg956
la source
8

Considérez que votre goulot d'étranglement pourrait être la performance d'E / S de votre système de fichiers.

En plus des paramètres suggérés par @RolandoMySQLDBA , j'ai également défini les noatimeparamètres de montage /etc/fstabde la partition contenant mon répertoire de données mysql ( /data01/mysqldans mon cas, avec mount /dev/sdb1to /data01).

Par défaut, Linux enregistre le temps d'accès pour CHAQUE lecture et écriture sur disque, ce qui a un impact négatif sur les performances d'E / S, en particulier pour les applications à E / S élevées, telles que les bases de données. Cela signifie que même la lecture de données à partir d'un fichier déclenche une écriture sur le disque ... WAT!

Pour désactiver ceci, ajoutez l' noatimeoption de montage dans /etc/fstabpour le point de montage souhaité comme suit (exemple dans mon cas):

/dev/sdb1  /data01  ext4  defaults,noatime  0  2

Puis remontez la partition:

mount -o,remount /data01

Cela devrait améliorer les performances de lecture / écriture des applications utilisant cette partition. MAIS ... rien ne vaut la conservation de toutes vos données en mémoire.

OkezieE
la source