À 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 partie where, donc la même colonne a été définie sur la même valeur pour toutes les lignes de la table et cela a été fait des milliers de fois et la colonne a été indexée, donc l'index correspondant a probablement été mis à jour trop de fois .
J'ai remarqué que quelque chose n'allait pas, car cela prenait trop de temps, alors j'ai tué le script. J'ai même redémarré mon ordinateur depuis lors, mais quelque chose est resté coincé dans le tableau, 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
C'est une table innodb, donc la transaction bloquée est probablement implicite. Comment puis-je corriger cette table et en supprimer la transaction bloquée?
SHOW FULL PROCESSLIST
?Réponses:
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 d'exécution, utilisez la commande suivante dans l'interface de ligne de commande mysql:
Il 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, afin que vous puissiez TUER les threads qui prennent trop de temps à 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'ID de thread, comme dans l'exemple suivant:
Cela mettra fin à la connexion pour le thread correspondant.
la source
Vous pouvez vérifier les transactions en cours avec
Votre transaction doit être l'une des premières, car c'est la plus ancienne de la liste. Maintenant, prenez simplement la valeur de
trx_mysql_thread_id
et envoyez-lui laKILL
commande: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.
la source
Vérifier l'état InnoDB pour les verrous
Vérifier les tables ouvertes MySQL
Vérifier les transactions InnoDB en attente
Vérifier la dépendance de verrouillage - ce qui bloque quoi
Après avoir étudié les résultats ci-dessus, vous devriez être en mesure de voir ce qui verrouille quoi.
La cause principale du problème peut également être dans votre code - veuillez vérifier les fonctions associées, en particulier pour les annotations si vous utilisez JPA comme Hibernate.
Par exemple, comme décrit ici , l'utilisation abusive de l'annotation suivante peut entraîner des verrous dans la base de données:
la source
SELECT * FROM information_schema.innodb_trx t JOIN information_schema.processlist p ON t.trx_mysql_thread_id = p.id
révélé le coupable: le thread de verrouillage provenait de mon adresse IP ... j'avais oublié de fermer une console de débogage que j'avais laissée au milieu d'une transaction ...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 existe probablement un moyen d'optimiser vos requêtes ou votre base de données, mais essayez ces 2 requêtes pour un correctif de contournement.
Lance ça:
Et puis ceci:
la source
Lorsque vous établissez une connexion pour une transaction, vous acquérez un verrou avant d'effectuer la transaction. Si vous ne parvenez pas à acquérir le verrou, vous essayez pendant un certain temps. Si le verrouillage ne peut toujours pas être obtenu, une erreur de dépassement du temps d'attente de verrouillage est levée. La raison pour laquelle vous ne pourrez pas acquérir un verrou 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 est toujours ouverte et maintient le verrou.
Solution: fermez la connexion ou
setAutoCommit(true)
(selon votre conception) pour libérer le verrou.la source
Redémarrez MySQL, cela fonctionne bien.
MAIS attention, si une telle requête est bloquée, il y a un problème quelque part:
LIKE %...%
, etc.)Comme l'a dit @syedrakib, 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.
Aussi, vous pouvez vérifier comment MySQL gère votre requête avec le mot-clé EXPLAIN et voir si quelque chose y est possible pour accélérer la requête (index, tests complexes, ...).
la source
Accéder aux processus dans mysql.
Vous pouvez donc voir qu'il y a encore une tâche à accomplir.
Tuez le processus particulier ou attendez la fin du processus.
la source
J'ai rencontré le même problème avec une déclaration "mise à jour". Ma solution consistait simplement à parcourir 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 supprimer la table et de la restaurer à partir d'une sauvegarde pour moi. :)
la source
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.
la source
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 (suppression en cascade de plusieurs enregistrements associés, cela simplifie la suppression de tous les enregistrements associés pour une seule suppression d'enregistrement).
J'ai essayé de parcourir les opérations disponibles dans phpMyAdmin pour la table (optimiser, vider, etc.), mais j'obtenais une autorisation nécessaire pour RELOAD erreur lorsque j'ai essayé de vider. Étant donné que ma base de données se trouve sur un serveur Web, je n'ai pas pu redémarrer la base de données. La restauration à partir d'une sauvegarde n'était pas une option.
J'ai essayé d'exécuter une requête de suppression pour ce groupe d'enregistrements sur l'accès mySQL de cPanel 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 y ai exécuté la requête de suppression. Cela a fonctionné tout de suite, le problème a été résolu. J'ai ensuite pu à nouveau exécuter la fonction en utilisant le script Access en utilisant la connexion ODBC Access to MySQL.
la source
Corrigé.
Assurez-vous que vous n'avez pas d'insertion de type de données incompatible dans la requête. J'ai eu un problème où j'essayais des "données d'agent du navigateur utilisateur"
VARCHAR(255)
et un problème avec ce verrou lorsque je l'ai changé enTEXT(255)
a corrigé.Il s'agit donc très probablement d'une incompatibilité de type de données.
la source
J'ai résolu le problème en supprimant la table et en la restaurant à partir d'une sauvegarde.
la source