moyen d'empêcher les requêtes d'attendre le verrouillage au niveau de la table

10

Nous avons rencontré un problème après avoir déplacé la base de données de notre client vers un serveur supplémentaire. Cela aurait dû avoir des effets positifs sur les performances du site, mais il y a un problème avec le verrouillage des tables dans MyISAM. (J'ai entendu parler d'InnoDB au lieu de MyISAM, mais nous ne pouvons pas changer le moteur dans un avenir proche).
Nous pourrions le repérer dans une mise à jour-requête qui est effectuée lorsqu'un modérateur active un commentaire sur le site d'articles. Voici le processus:

  • la requête de mise à jour est traitée SET status = 1 WHERE id = 5(l'index est défini)
  • les fichiers mis en cache de la page sont supprimés

À ce stade, la page entière devient lente. La base de données elle-même est occupée pendant quelques minutes. J'ai récupéré la liste de processus à plusieurs reprises et j'ai vu environ 60 entrées de différentes requêtes de sélection, qui étaient toutes en attente de verrouillage au niveau de la table .

1. Je ne comprends pas pourquoi cette mise à jour sur la table article_commentspeut affecter les instructions select pour que la table articleattende le verrouillage au niveau de la table. Dans processlist, presque toutes les requêtes en attente provenaient de cette table. J'ai lu que les mises à jour / insertions sont préférées aux sélections et que cela peut causer de tels problèmes, mais le tableau des articles lui-même n'est pas mis à jour lorsque les commentaires sont activés, donc les sélections ne doivent pas attendre. Ai-je mal compris cela?
2. Y a-t-il autre chose que le passage à InnoDB pour empêcher ce comportement ou au moins pour obtenir un meilleur équilibre? Je suis très irrité du fait que ce problème ne soit pas apparu avant de déplacer la base de données vers le nouveau serveur. Je suppose qu'il y a une mauvaise configuration mais je ne sais pas comment l'identifier.

32bitfloat
la source
1
Activez la journalisation générale et surveillez les instructions JOIN entre ces tables. Lorsque vous sélectionnez, il crée un verrou de lecture implicite. Étant donné que MYISAM ne prend pas en charge le verrouillage ROW LEVEL, il se verrouille au niveau de la table. C'est probablement le cas que ce verrouillage se produisait sur l'ancien serveur mais que personne ne regardait? Comparez votre ligne my.cnf pour la ligne entre les hôtes et surtout assurez-vous que votre key_buffer est réglé correctement.
randomx
Nous avons eu plusieurs autres problèmes de performances sur l'ancien serveur et avons souvent regardé la liste des processus. Il y avait principalement de nombreux processus de sommeil, mais nous n'avons jamais remarqué de processus en attente (j'ai généralement vu cette information la première fois sur ce nouveau serveur). Mon collègue a copié l'ancien my.cnf et ajusté les valeurs au nouveau matériel existant, mais il n'y avait pas beaucoup d'entrées. J'ai également comparé les sorties de "SHOW VARIABLES" mais je ne savais pas vraiment quoi regarder. Nous revérifierons le keybuffer demain, merci pour votre commentaire.
32bitfloat
Nous avons récemment eu un problème similaire. Initialement, notre key_buffer_sizeétait réglé sur 1GB. Augmenter cela pour 10GBréduire le problème.
Haluk
@ Rick James, merci. Tu m'as sauvé beaucoup de problèmes aujourd'hui. Avez-vous une liste de souhaits sur Amazon ou ailleurs? :) J'ai configuré query_cache_limit à 1024. Il n'y a plus de problème de verrouillage maintenant. Je l'ai fait dans des variables au départ du client mysql. définissez global query_cache_limit = 1024; Maintenant, je vais l'écrire sur my.cnf. Cette solution m'a donné le temps de planifier la migration innodb sans stress, alors merci.

Réponses:

8

Le moteur de stockage MyISAM est furieusement connu pour effectuer des verrous de table complets pour tout DML (INSERT, UPDATEs, DELETEs). InnoDB résoudrait définitivement ce problème à long terme.

J'ai écrit sur les avantages et les inconvénients de l'utilisation de MyISAM vs InnoDB

En ce qui concerne votre question actuelle, voici un scénario possible:

  • articleet article_commentssont les deux tables MyISAM
  • article_commentsa un ou plusieurs index avec statuscomme colonne
  • Les mises à jour des pages d'index pour article_commentssont mises en cache dans le tampon de clés MyISAM (dimensionnées par key_buffer_size ), entraînant la sortie des anciennes pages d'index du tampon de clés MyISAM
  • Vous avez des requêtes SELECT qui effectuent des JOIN entre articleetarticle_comments

Dans mon scénario suggéré, les SELECT sur la articletable peuvent être empêchés d'autoriser les écritures car ils doivent attendre article_commentsd'être libres de tout DML (dans ce cas, un UPDATE)

RolandoMySQLDBA
la source
Merci pour votre réponse (et les liens), votre scénario est réel. Je ne savais pas que la plupart des articles sélectionnés rejoignaient en effet la table des commentaires (ou en d'autres termes, ont vu les déclarations incomplètes dans processlist de phpmyadmin). Connaissez-vous une solution à court terme pour éviter les multiples requêtes en attente? Je l'ai déjà essayé avec "UPDATE LOW_PRIORITY" dans la déclaration spécifique, mais cela n'a pas apporté de modifications notables. Nous allons vraiment passer à innodb à l'avenir, mais je me demande s'il y a un moyen d'obtenir une amélioration actuellement.
32bitfloat
Solution ultime: convertir des tables en InnoDB. Voir mon article dba.stackexchange.com/a/9422/877 sur la façon de convertir tout MyISAM en InnoDB
RolandoMySQLDBA
7

À ce stade, la page entière devient lente. La base de données elle-même est occupée pendant quelques minutes.

Ça sent comme vous avez un gros Query_cache?

mysql> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 | -- Not over 50M
| query_cache_type             | DEMAND   | -- Only if using SQL_CACHE
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

Pour les systèmes de production avec beaucoup d'écritures, vous pouvez aussi désactiver le query_cache.

Toutes les entrées de la query_cache pour la table donnée sont purgés lorsque toute écriture se produit à cette table. Plus le QC est grand, plus cette tâche est lente.

MyISAM utilise des verrous de "niveau table". Les lectures et les écritures ne peuvent pas avoir lieu en même temps (sur la même table). Brut, mais efficace.

Rick James
la source
1
Hé bien oui. Nous avons environ 64 millions de caches. Merci pour cette information qui était nouvelle pour moi, cependant, nous avions la même valeur sur l'ancien serveur où nous n'avions pas remarqué les verrouillages. Nous avons déjà commencé à passer à InnoDB mais ce fait reste un mystère ...
32bitfloat