À 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?
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.
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.
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;
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)
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 @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, ...).
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.
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é.
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.
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
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.
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. :)