J'exécute l' UPDATE
instruction MySQL suivante :
mysql> update customer set account_import_id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
Je n'utilise pas de transaction, alors pourquoi aurais-je cette erreur? J'ai même essayé de redémarrer mon serveur MySQL et cela n'a pas aidé.
Le tableau comporte 406 733 lignes.
mysql
sql
timeout
lock-timeout
Jason Swett
la source
la source
process
soient inactives. Si c'est le cas, vous pourriez obtenir cette erreur. Ai-je raison?connection.commit()
pour valider leINSERT
ouUPDATE
que vous venez de parcourir.Comment forcer le déverrouillage pour les tables verrouillées dans MySQL:
Le fait de casser des verrous comme celui-ci peut empêcher l' atomicité de la base de données sur les instructions sql à l'origine du verrou.
C'est hackish, et la bonne solution est de corriger votre application qui a provoqué les verrous. Cependant, lorsque les dollars sont en jeu, un coup de pied rapide fera bouger les choses à nouveau.
1) Entrez dans MySQL
2) Voyons la liste des tables verrouillées
3) Voyons la liste des processus en cours, l'un d'eux verrouille votre table (s)
4) Tuez l'un de ces processus
la source
Déclenchez à nouveau le verrou. Vous avez 100 secondes pour émettre un
SHOW ENGINE INNODB STATUS\G
dans la base de données et voir quelle autre transaction verrouille la vôtre.la source
lock_wait_timeout
valeurVérifiez si votre base de données est bien réglée. Surtout l'isolement des transactions. Ce n'est pas une bonne idée d'augmenter la variable innodb_lock_wait_timeout.
Vérifiez le niveau d'isolement des transactions de votre base de données dans le CLI mysql:
Vous pouvez obtenir des améliorations en changeant le niveau d'isolation, utilisez l'oracle comme READ COMMITTED au lieu de REPEATABLE READ (InnoDB Defaults)
Essayez également d'utiliser SELECT FOR UPDATE uniquement si nécessaire.
la source
tx_isolation
variable entransaction_isolation
.Aucune des solutions suggérées n'a fonctionné pour moi mais cela a fonctionné.
Quelque chose bloque l'exécution de la requête. Une autre requête est probablement mise à jour, insérée ou supprimée d'une des tables de votre requête. Vous devez découvrir ce que c'est:
Une fois que vous avez localisé le processus de blocage, recherchez-le
id
et exécutez:Relancez votre requête initiale.
la source
100% avec ce que MarkR a dit. autocommit fait de chaque instruction une transaction d'une instruction.
SHOW ENGINE INNODB STATUS
devrait vous donner quelques indices sur la raison de l'impasse. Jetez également un œil à votre journal des requêtes lentes pour voir ce qui est en train d'interroger la table et essayez de supprimer tout ce qui fait un scan complet de la table. Le verrouillage au niveau des lignes fonctionne bien, mais pas lorsque vous essayez de verrouiller toutes les lignes!la source
Pouvez-vous mettre à jour tout autre enregistrement de cette table ou cette table est-elle fortement utilisée? Ce que je pense, c'est que pendant qu'il tente d'acquérir un verrou dont il a besoin pour mettre à jour cet enregistrement, le délai d'expiration défini a expiré. Vous pourrez peut-être augmenter le temps qui peut vous aider.
la source
innodb_lock_wait_timeout
dansmy.cnf
Le nombre de lignes n'est pas énorme ... Créez un index sur account_import_id si ce n'est pas la clé primaire.
la source
Si vous venez de tuer une grosse requête, cela prendra du temps
rollback
. Si vous émettez une autre requête avant la fin de la requête supprimée, vous pouvez obtenir une erreur de délai d'expiration du verrouillage. C'est ce qui m'est arrivé. La solution était d'attendre un peu.Détails:
J'avais émis une requête DELETE pour supprimer environ 900 000 sur environ 1 million de lignes.
J'ai exécuté cela par erreur (ne supprime que 10% des lignes):
DELETE FROM table WHERE MOD(id,10) = 0
Au lieu de cela (supprime 90% des lignes):
DELETE FROM table WHERE MOD(id,10) != 0
Je voulais supprimer 90% des lignes, pas 10%. J'ai donc tué le processus dans la ligne de commande MySQL, sachant qu'il annulerait toutes les lignes qu'il avait supprimées jusqu'à présent.
Ensuite, j'ai exécuté la commande correcte immédiatement et j'ai reçu une
lock timeout exceeded
erreur peu de temps après. J'ai réalisé que le verrou pourrait en fait être larollback
requête tuée qui se produit toujours en arrière-plan. J'ai donc attendu quelques secondes et relancé la requête.la source
Assurez-vous que les tables de base de données utilisent le moteur de stockage InnoDB et le niveau d'isolement des transactions READ-COMMITTED.
Vous pouvez le vérifier par SELECT @@ GLOBAL.tx_isolation, @@ tx_isolation; sur la console mysql.
S'il n'est pas configuré pour être LECTURE ENGAGÉE, vous devez le définir. Assurez-vous avant de le définir que vous avez des privilèges SUPER dans mysql.
Vous pouvez obtenir de l'aide sur http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html .
En réglant cela, je pense que votre problème sera résolu.
Vous pouvez également vérifier que vous n'essayez pas de mettre à jour cela dans deux processus à la fois. Les utilisateurs (@tala) ont rencontré des messages d'erreur similaires dans ce contexte, peut-être vérifier que ...
la source
Je viens de Google et je voulais juste ajouter la solution qui fonctionnait pour moi. Mon problème était que j'essayais de supprimer les enregistrements d'une énorme table qui avait beaucoup de FK en cascade, donc j'ai eu la même erreur que l'OP.
J'ai désactivé le
autocommit
puis cela a fonctionné simplement en ajoutantCOMMIT
à la fin de la phrase SQL. Pour autant que je sache, cela libère le tampon bit par bit au lieu d'attendre à la fin de la commande.Pour conserver l'exemple du PO, cela aurait dû fonctionner:
mysql> set autocommit=0;
mysql> update customer set account_import_id = 1; commit;
N'oubliez pas de réactiver le
autocommit
si vous souhaitez laisser la configuration MySQL comme avant.mysql> set autocommit=1;
la source
Tard dans la soirée (comme d'habitude) mais mon problème était le fait que j'ai écrit du mauvais SQL (étant un novice) et que plusieurs processus avaient un verrou sur le (s) enregistrement (s) <- je ne suis pas sûr du verbiage approprié. J'ai fini par devoir simplement:
SHOW PROCESSLIST
puis tuer les identifiants en utilisantKILL <id>
la source
Ce genre de chose m'est arrivé lorsque j'utilisais la sortie de construction de langage php; au milieu de la transaction. Ensuite, cette transaction "se bloque" et vous devez tuer le processus mysql (décrit ci-dessus avec processlist;)
la source
Dans mon cas, j'exécutais une requête anormale pour corriger les données. Si vous verrouillez les tables dans votre requête, vous n'aurez pas à gérer le délai de verrouillage:
Ce n'est probablement pas une bonne idée pour une utilisation normale.
Pour plus d'informations, voir: MySQL 8.0 Reference Manual
la source
J'ai rencontré 2 connexions Doctrine DBAL, dont une non-transactionnelle (pour les journaux importants), elles sont destinées à fonctionner en parallèle sans dépendre l'une de l'autre.
Mes tests d'intégration ont été enveloppés dans des transactions pour la restauration des données après un test très poussé.
Ma solution a été de désactiver la transaction d'encapsulation dans ces tests et de réinitialiser les données db d'une autre manière.
la source
J'ai eu la même erreur, même si je ne mettais à jour qu'une table avec une entrée, mais après avoir redémarré mysql, elle a été résolue.
la source