Si j'utilise mysqldump --single-transaction, selon les documents, il devrait faire des tables de vidage avec verrou en lecture pour obtenir un état cohérent, puis démarrer une transaction et aucun écrivain ne devrait attendre.
Cependant, j'ai constaté hier soir la situation suivante:
extrait de la liste complète des processus:
des centaines de ces ...
Command: Query
Time: 291
State: Waiting for table flush
Info: insert into db_external_notification.....
ensuite ceci:
Command: Query
Time: 1204
State: Sending data
Info: SELECT /*!40001 SQL_NO_CACHE */ * FROM `db_external_notification`
et le reste des fils sont en veille
Quelqu'un a-t-il une idée de ce qu'attendent ces inserts? Je ne vois aucune table FLUSH ou DDL ou quoi que ce soit mentionné dans le manuel qui puisse faire attendre les requêtes.
commande mysqldump complète
mysqldump --quick --add-drop-table --single-transaction --master-data=2 -uxx -pxx dbname
Je suppose que --quick est redondant ici, probablement un reste des temps précédents, ce script est très ancien, mais ne devrait pas faire de mal
mysqldump
? En particulier, utilisez-vous--flush-logs
ou--master-data
...? Il existe des interactions potentielles entre les options.Réponses:
L' option --single-transaction de mysqldump ne fonctionne pas
FLUSH TABLES WITH READ LOCK;
. Il provoque mysqldump pour configurer une transaction de lecture répétable pour toutes les tables en cours de vidage.De votre question, vous avez déclaré que le SELECT de mysqldump pour la
db_external_notification
table contient des centaines de commandes INSERT sur cette même table. Pourquoi cela arrive-t-il ?La chose la plus probable est un verrou sur le gen_clust_index (mieux connu sous le nom d'index clusterisé). Ce paradigme fait coexister des données et des pages d'index pour une table. Ces pages d'index sont basées soit sur la PRIMARY KEY, soit sur un index RowID généré automatiquement (dans le cas où il n'y a pas de PRIMARY KEY).
Vous devriez être capable de repérer cela en exécutant
SHOW ENGINE INNODB STATUS\G
et en recherchant n'importe quelle page de gen_clust_index qui a un verrou exclusif. Faire des INSERT dans une table avec un index clusterisé nécessite un verrou exclusif pour gérer le BTREE de la PRIMARY KEY, ainsi que la sérialisation de l'auto_increment.J'ai déjà discuté de ce phénomène
Aug 08, 2011
: Les blocages InnoDB sont - ils exclusifs à INSERT / UPDATE / DELETE?Dec 22, 2011
: Blocage MySQL - ne peut pas redémarrer normalement?Dec 13, 2012
: MySQL InnoDB verrouille la clé primaire lors de la suppression même en LECTURE COMMISEMISE À JOUR 2014-07-21 15:03 EDT
Veuillez regarder les lignes 614-617 de votre PastBin
Notez que la ligne 617 indique
Qu'est-ce que cela me dit? Vous avez une CLÉ PRIMAIRE avec un auto_increment activé
id
.Votre maximum
id
pour la tabledb_external_notification
était inférieur à celui1252538391
du lancement de mysqldump. Lorsque vous soustrayez1252538391
de1252538405
, cela signifie que 14 commandes INSERT ou plus ont été tentées. En interne, cela devrait déplacer au moins 14 fois l'auto_increment de cette table. Pourtant, rien ne peut être engagé ou même poussé dans le tampon de journal en raison de la gestion de cetid
écart.Maintenant, regardez la liste des processus de votre PasteBin. Sauf erreur de calcul, j'ai vu 38 connexions DB effectuer un INSERT (19 avant le processus mysqldump (identifiant du processus
6155315
), 19 après). Je suis sûr que 14 ou plus de ces connexions sont gelées en raison de la gestion de l'écart auto_increment.la source
L'
--single-transaction
option demysqldump
fait unFLUSH TABLES WITH READ LOCK
avant de démarrer la tâche de sauvegarde, mais uniquement sous certaines conditions. L'une de ces conditions est lorsque vous spécifiez également l'--master-data
option.Dans le code source, à partir
mysql-5.6.19/client/mysqldump.c
de la ligne 5797:Pour obtenir un verrou solide sur les coordonnées binlog précises avant de commencer la transaction de lecture répétable, l'
--master-data
option déclenche l'obtention de ce verrou, puis le relâche une fois les coordonnées binlog obtenues.En fait,
mysqldump
fait unFLUSH TABLES
suivi d'unFLUSH TABLES WITH READ LOCK
parce que faire les deux choses permet d'obtenir le verrou de lecture plus rapidement dans les cas où le vidage initial prend un certain temps....toutefois...
Dès qu'il a obtenu les coordonnées binlog,
mysqldump
émet uneUNLOCK TABLES
instruction, il ne devrait donc pas y avoir de blocage à la suite du vidage que vous avez commencé. Aucun thread ne doit nonWaiting for table flush
plus résulter de la transaction en coursmysqldump
.Lorsque vous voyez un thread dans l'
Waiting for table flush
état, cela devrait signifier que l'FLUSH TABLES [WITH READ LOCK]
instruction a été émise et était toujours en cours d'exécution au démarrage de la requête - la requête doit donc attendre le vidage de la table avant de pouvoir s'exécuter. Dans le cas de la liste de processus que vous avez publiée,mysqldump
lit à partir de ce même tableau, et la requête est en cours d'exécution depuis un certain temps, mais les requêtes de blocage ne bloquent pas depuis si longtemps.Tout cela suggère que quelque chose d'autre s'est produit.
Il y a un problème de longue date expliqué dans le bogue # 44884 avec le
FLUSH TABLES
fonctionnement interne.Je ne serais pas surpris si le problème persiste,je serais surpris si ce problème est jamais "résolu" car il s'agit d'un problème très complexe à résoudre - pratiquement impossible à résoudre véritablement dans un environnement à forte concurrence - et toute tentative de le réparer comporte un risque important de casser quelque chose d'autre ou de créer un comportement nouveau, différent et toujours indésirable.Il semble probable que ce sera l'explication de ce que vous voyez.
Plus précisément:
si vous avez une requête de longue durée exécutée sur une table et émettez
FLUSH TABLES
, alors leFLUSH TABLES
bloquera jusqu'à ce que la requête de longue durée se termine.en outre, toutes les requêtes qui commencent après l'
FLUSH TABLES
émission du sont bloquées jusqu'à ce que leFLUSH TABLES
soit terminé.en outre, si vous supprimez la
FLUSH TABLES
requête, les requêtes qui bloquent seront toujours bloquées sur la requête de longue durée d'origine, celle qui bloquait laFLUSH TABLES
requête, car même si laFLUSH TABLES
requête tuée ne s'est pas terminée, cette table (celle ou plus, impliqué dans la requête de longue durée) est toujours en cours de vidage, et ce vidage en attente va se produire dès que la requête de longue durée se termine - mais pas avant.La conclusion probable ici est qu'un autre processus - peut-être un autre mysqldump, ou une requête mal avisée, ou un processus de surveillance mal écrit a tenté de vider une table.
Cette requête a ensuite été supprimée ou expirée par un mécanisme inconnu, mais ses séquelles ont persisté jusqu'à la
mysqldump
fin de la lecture du tableau en question.Vous pouvez répliquer cette condition en essayant
FLUSH TABLES
pendant qu'une requête de longue durée est en cours. Ensuite, lancez une autre requête, qui se bloquera. Tuez ensuite laFLUSH TABLES
requête, qui ne débloquera pas la dernière requête. Ensuite, supprimez la première requête ou laissez-la se terminer, et la requête finale s'exécutera avec succès.Après coup, cela n'est pas lié:
C'est normal, car le
mysqldump --single-transaction
problème aSTART TRANSACTION WITH CONSISTENT SNAPSHOT
, qui l'empêche de vider les données modifiées pendant le vidage. Sans cela, les coordonnées binlog obtenues au départ n'auraient aucun sens, car la--single-transaction
ne serait pas ce qu'elle prétend être. Cela ne devrait en aucun cas être lié auWaiting for table flush
problème, car cette transaction ne comporte évidemment aucun verrou.la source
J'ai soumis une demande de fonctionnalité: https://support.oracle.com/epmos/faces/BugDisplay?id=27103902 .
J'ai également écrit un correctif contre 5.6.37 qui utilise la même méthode que la combinaison --single-transaction --master-data avec --single-transaction --slave-data, qui est fourni tel quel sans garantie. À utiliser à vos risques et périls.
Je l'ai testé avec le processus suivant avec des esclaves vers un maître très occupé en utilisant beaucoup de tables InnoDB avec des relations FK:
Le processus de soumission des correctifs d'Oracle est assez intensif, c'est pourquoi j'ai choisi cette voie. Je peux essayer avec Percona et / ou MariaDB pour l'intégrer.
la source