web-dev-qa-db-fra.com

Correction du dépassement du délai d'attente de verrouillage; essayez de redémarrer la transaction "pour une table Mysql" bloquée "?

À partir d'un script, j'ai envoyé une requête semblable à celle-ci des milliers de fois à ma base de données locale:

update some_table set some_column = some_value

J'ai oublié d'ajouter la partie where, de sorte que la même colonne a la même valeur pour toutes les lignes de la table. Cette opération a été effectuée des milliers de fois et la colonne a été indexée. L'index correspondant a donc probablement été mis à jour trop souvent. .

J'ai remarqué que quelque chose n'allait pas, parce que cela a pris trop de temps, alors j'ai tué le script. J'ai même redémarré mon ordinateur depuis lors, mais quelque chose est resté bloqué dans la table, car les requêtes simples prennent beaucoup de temps à s'exécuter et lorsque j'essaie de supprimer l'index pertinent, ce dernier échoue avec le message suivant:

Lock wait timeout exceeded; try restarting transaction

C'est une table innodb, la transaction est donc probablement implicite. Comment puis-je corriger cette table et supprimer la transaction bloquée?

112
Tom

J'ai eu un problème similaire et je l'ai résolu en vérifiant les threads en cours d'exécution. Pour voir les threads en cours, utilisez la commande suivante dans l'interface de ligne de commande mysql:

SHOW PROCESSLIST;

Il peut également être envoyé depuis phpMyAdmin si vous n'avez pas accès à l'interface de ligne de commande mysql.
Ceci affichera une liste de threads avec les identifiants et le temps d’exécution correspondants, de sorte que vous puissiez TUER les threads dont l’exécution prend trop de temps. Dans phpMyAdmin, vous aurez un bouton pour arrêter les threads à l'aide de KILL. Si vous utilisez l'interface de ligne de commande, utilisez simplement la commande KILL suivie de l'identifiant du thread, comme dans l'exemple suivant:

KILL 115;

Cela mettra fin à la connexion pour le thread correspondant.

128
Mihai Crăiță

Vous pouvez vérifier les transactions en cours avec

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`

Votre transaction devrait être l'une des premières, car c'est la plus ancienne de la liste. Maintenant, prenez la valeur de trx_mysql_thread_id et envoyez-lui la commande KILL:

KILL 1234;

Si vous ne savez pas quelle transaction est la vôtre, répétez la première requête très souvent et voyez quelles transactions persistent.

42
nlsrchtr

Cela a commencé à arriver lorsque la taille de ma base de données a augmenté et que je faisais beaucoup de transactions dessus.

La vérité est qu'il existe probablement un moyen d'optimiser vos requêtes ou votre base de données, mais essayez ces 2 requêtes pour résoudre le problème.

Lance ça:

SET GLOBAL innodb_lock_wait_timeout = 5000; 

Et puis ceci:

SET innodb_lock_wait_timeout = 5000; 
31
Max D

Vérifier l'état d'InnoDB pour les verrous

SHOW ENGINE InnoDB STATUS;

Vérifiez les tables ouvertes MySQL

SHOW OPEN TABLES WHERE In_use > 0;

Vérifier les transactions InnoDB en attente

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`; 

Vérifier la dépendance de verrouillage - ce qui bloque quoi

SELECT * FROM `information_schema`.`innodb_locks`;

Après avoir examiné les résultats ci-dessus, vous devriez être en mesure de voir ce qui bloque quoi.

La cause première du problème pourrait également se trouver dans votre code - veuillez vérifier les fonctions associées, en particulier les annotations, si vous utilisez JPA comme Hibernate.

Par exemple, comme décrit ici , une mauvaise utilisation de l'annotation suivante peut provoquer des verrous dans la base de données:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
29
martoncsukas

Redémarrez MySQL, cela fonctionne bien.

MAIS Attention, si une telle requête est bloquée, il y a un problème quelque part:

  • dans votre requête (caractère mal placé, produit cartésien, ...)
  • très nombreux disques à éditer
  • jointures complexes ou tests (MD5, sous-chaînes, LIKE %...%, etc.)
  • problème de structure de données
  • modèle de clé étrangère (verrouillage chaîne/boucle)
  • données mal indexées

Comme @syedrakib l'a dit, cela fonctionne, mais ce n'est pas une solution durable pour la production.

Attention: le redémarrage peut affecter vos données avec un état incohérent.

En outre, vous pouvez vérifier comment MySQL traite votre requête avec le mot clé EXPLAIN et voir s’il est possible de le rendre plus rapide (index, tests complexes, ...).

7
Benj

Lorsque vous établissez une connexion pour une transaction, vous acquérez un verrou avant d'effectuer la transaction. Si vous ne pouvez pas obtenir le verrou, vous essayez pendant un certain temps. Si le verrouillage ne peut toujours pas être obtenu, une erreur dépassant le délai d'attente du verrou est levée. Pourquoi vous ne pouvez pas obtenir un verrou, c'est que vous ne fermez pas la connexion. Ainsi, lorsque vous essayez d'obtenir un verrou une deuxième fois, vous ne pourrez pas acquérir le verrou car votre connexion précédente n'est toujours pas fermée et le verrouille.

Solution: fermez la connexion ou configurez AutoCommit (true) [selon votre conception] pour libérer le verrou.

5
user3388324

Aller aux processus dans mysql.

Donc, vous pouvez voir que la tâche continue de fonctionner.

Tuez le processus particulier ou attendez que le processus soit terminé.

3
Shemeer M Ali

J'ai eu ce problème en essayant de supprimer un certain groupe d'enregistrements (en utilisant MS Access 2007 avec une connexion ODBC à MySQL sur un serveur Web). En règle générale, je supprimerais certains enregistrements de MySQL, puis les remplacerais par des enregistrements mis à jour (supprimer en cascade plusieurs enregistrements associés, ce qui simplifie la suppression de tous les enregistrements associés pour une seule suppression d'enregistrement).

J'ai essayé de passer en revue les opérations disponibles dans phpMyAdmin pour la table (optimiser, vidage, etc.), mais je recevais une autorisation nécessaire pour reloger l'erreur lorsque j'essayais de vider. Comme ma base de données est sur un serveur Web, je ne pouvais pas la redémarrer. Restaurer à partir d'une sauvegarde n'était pas une option.

J'ai essayé d'exécuter la requête de suppression pour ce groupe d'enregistrements sur l'accès cPanel mySQL sur le Web. Vous avez le même message d'erreur.

Ma solution: j'ai utilisé le navigateur de requêtes MySQL gratuit de Sun (Oracle) (que j'avais précédemment installé sur mon ordinateur) et j'ai exécuté la requête de suppression à cet endroit. Cela a fonctionné tout de suite, le problème a été résolu. J'ai alors pu à nouveau exécuter la fonction à l'aide du script Access à l'aide de la connexion ODBC Access to MySQL.

1
Mike Lane

Corrigé, assurez-vous que le type de données utilisé ne correspond pas mal à la requête. J'avais un problème où j'essayais "données d'agent de navigateur utilisateur" dans "VARCHAR (255)" et ayant un problème avec ce verrou, mais lorsque je l'ai changé en "TEXT (255)", il a été corrigé. Donc, le plus probable est une mauvaise correspondance du type de données

0
Hiren Raj

J'ai eu le même problème. Je pense que c'était un problème de blocage avec SQL. Vous pouvez simplement forcer la fermeture du processus SQL à partir du Gestionnaire des tâches. Si cela ne résout pas le problème, redémarrez simplement votre ordinateur. Vous n'avez pas besoin de supprimer la table et de recharger les données.

0
kriver

J'ai rencontré le même problème avec un "update" -atatement. Ma solution consistait simplement à exécuter les opérations disponibles dans phpMyAdmin pour la table. J'ai optimisé, vidé et défragmenté la table (pas dans cet ordre). Pas besoin de laisser tomber la table et de la restaurer à partir d'une sauvegarde pour moi. :)

0
The Science Boy