148 votes

Correction de "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 comme 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 clause where, donc la même colonne a été définie avec la même valeur pour toutes les lignes de la table et cela a été fait des milliers de fois et la colonne était indexée, donc l'index correspondant a probablement été mis à jour de nombreuses fois également.

J'ai remarqué quelque chose d'anormal car cela prenait trop de temps, j'ai donc interrompu le script. J'ai même redémarré mon ordinateur depuis, 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, cela échoue avec ce message :

Lock wait timeout exceeded; try restarting transaction

Il s'agit d'une table innodb, donc le blocage de la transaction est probablement implicite. Comment puis-je corriger cette table et supprimer la transaction bloquée ?

3 votes

Quel est le résultat de SHOW FULL PROCESSLIST ?

0 votes

Il affiche uniquement la commande SHOW FULL PROCESSLIST, rien d'autre. C'est une base de données de développement locale. Rien ne s'y exécute. J'ai reçu le message d'erreur 'lock wait..' sur la ligne de commande lorsque j'ai essayé de supprimer l'index à partir de là.

0 votes

Dans ce cas, vous créez probablement 2 connexions séparées dans des transactions différentes qui doivent attendre l'une l'autre.

153voto

Mihai Crăiță Points 645

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

SHOW PROCESSLIST;

Cela peut également être envoyé depuis phpMyAdmin si vous n'avez pas accès à l'interface de ligne de commande mysql.
Cela affichera une liste de threads avec les identifiants correspondants et le temps d'exécution, vous pouvez donc KILL les threads qui prennent trop de temps pour s'exécuter. Dans phpMyAdmin, vous aurez un bouton pour arrêter les threads en utilisant 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 terminera la connexion pour le thread correspondant.

41 votes

PRENEZ NOTE! Cela a été mentionné par quelqu'un sur l'un des nombreux fils SO concernant ce problème: Parfois, le processus qui a verrouillé la table apparaît comme dormant dans la liste des processus! Je me tirais les cheveux jusqu'à ce que j'ai tué tous les threads qui étaient ouverts dans la base de données en question, dormant ou non. Cela a finalement déverrouillé la table et a permis à la requête de mise à jour de fonctionner. Le commentateur a mentionné quelque chose comme "Parfois, un thread MySQL verrouille une table, puis dort en attendant quelque chose qui n'est pas lié à MySQL."

0 votes

J'ai ajouté ma propre réponse pour développer ce fragment de pensée ici, sur une question connexe

0 votes

Cela m'a aidé. J'avais quelques fils de discussion dormants créés par la fonction de gestion/requête de base de données PHPStorm.

46voto

Max D Points 13

Cela a commencé à m'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 y a probablement un moyen d'optimiser soit vos requêtes soit votre base de données, mais essayez ces 2 requêtes pour contourner le problème.

Exécutez ceci :

SET GLOBAL innodb_lock_wait_timeout = 5000; 

Et ensuite ceci :

SET innodb_lock_wait_timeout = 5000;

2 votes

Lien de référence : innodb_lock_wait_timeout

1 votes

Je gère une base de données très chargée de 11 Go. C'est la seule chose qui a fonctionné pour moi, merci!

0 votes

N'oubliez pas simplement de modifier les valeurs pour les remettre à leurs valeurs précédentes si vous ne voulez pas les conserver indéfiniment.

9voto

Benj Points 477

Redémarrez MySQL, cela fonctionne bien.

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

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

Comme l'a dit @syedrakib, ça fonctionne mais ce n'est pas une solution viable à long terme pour la production.

Attention : redémarrer peut affecter vos données en les laissant dans un état incohérent.

De plus, vous pouvez vérifier comment MySQL gère votre requête avec le mot clé EXPLAIN et voir s'il est possible d'optimiser la requête (index, tests complexes,...).

0 votes

MERCI. vous n'avez pas résolu mon problème directement mais j'ai souffert des verrous de table et c'était si mauvais. C'est le seul message sur tout internet, qui m'a conduit à l'idée de vérifier les clés étrangères. J'ai donc découvert que la clé de la clé primaire était 11 et les clés étrangères 10. Je ne sais pas comment cela a pu arriver et pourquoi tout fonctionnait avant.

0 votes

@EscapeNetscape de rien, je suis content que cette petite réponse vous ait aidé :)

3voto

shemeermali Points 547

Accéder aux processus dans mysql.

Vous verrez qu'il y a encore une tâche en cours.

Arrêtez le processus particulier ou attendez qu'il se termine.

9 votes

Il résout le problème. Mais cela ne peut pas être une solution pour un serveur de production EN DIRECT...... Comment pouvons-nous afficher cette gestion des interblocages? Ou comment pouvons-nous ÉVITER que ce blocage ne se produise?

1 votes

Eh bien, il se trouve que même avec des requêtes mysql PARFAITEMENT bien formées et PARFAITEMENT échappées qui ne sont même pas écrites par le développeur mais par l'interface des active-records du framework, des problèmes de temps d'attente de verrouillage peuvent ENCORE se produire. Donc je ne pense pas que le fait d'écrire une requête mysql correcte soit un facteur ici.

1voto

Mike Lane Points 11

J'ai rencontré 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 général, je supprimais certains enregistrements de MySQL puis les remplaçais par des enregistrements mis à jour (supprimant en cascade plusieurs enregistrements liés, ce qui simplifie la suppression de tous les enregistrements liés pour une seule suppression).

J'ai essayé d'exécuter les opérations disponibles dans phpMyAdmin pour la table (optimiser, vider, etc), mais j'ai obtenu une erreur de permission nécessaire pour RELOAD lorsque j'ai essayé de vider. Comme ma base de données est sur un serveur web, je ne pouvais pas redémarrer la base de données. La restauration à 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 MySQL du cPanel sur le web. J'ai obtenu le même message d'erreur.

Ma solution : J'ai utilisé le MySQL Query Browser gratuit de Sun (Oracle) (que j'avais précédemment installé sur mon ordinateur) et j'ai exécuté la requête de suppression là-bas. Ça a marché tout de suite, Problème résolu. J'ai ensuite pu à nouveau exécuter la fonction en utilisant le script Access en utilisant la connexion ODBC d'Access à MySQL.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X