web-dev-qa-db-fra.com

Laravel - Délai d'attente de verrouillage dépassé

J'ai beaucoup de transactions dans mon code, et si une erreur survient lors de l'exécution de l'une de ces transactions qui ne déclenche pas la validation ou l'annulation, la base de données est verrouillée et toute tentative ultérieure d'accéder à la base de données entraîne ceci:

production.ERROR: PDOException: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction in /home/forge/default/vendor/laravel/framework/src/Illuminate/Database/Connection.php:390

Dans le contrôleur:

DB::beginTransaction();

try {
    //Code that uses exec() to process some images. <-- If code breaks here, then the above error appears on subsequent requests.
    //Code that accesses the database
}
catch(\Exception $e){
    DB::rollback();
    throw $e;
}
DB::commit();

Donc, même php artisan migrate: refresh ou php artisan migrate: reset cesse également de fonctionner. Comment dois-je résoudre ce problème?

9
Andrew

Je vois une question en double

Comment déboguer le délai d'attente de verrouillage dépassé sur MySQL?

Vous devriez augmenter la valeur du délai d'attente de verrouillage pour InnoDB en définissant innodb_lock_wait_timeout (la valeur par défaut est 50 secondes).

mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 50    |
+--------------------------+-------+
1 row in set (0.01 sec)

Vous pouvez lui attribuer une valeur supérieure dans /etc/my.cnf de manière permanente avec cette ligne.

[mysqld]
innodb_lock_wait_timeout=120

et redémarrez mysql. Si vous ne pouvez pas redémarrer mysql à ce stade, lancez ceci:

SET GLOBAL innodb_lock_wait_timeout = 120`; 

Vous pouvez également simplement le définir pour la durée de votre session

SET innodb_lock_wait_timeout = 120; 
4
TinhNQ

Voici quelques conseils de mon expérience ...

Si vous effectuez un développement piloté par des tests, indiquez quelle combinaison de tests génère l'erreur. Utilisez le mécanisme fourni par votre écosystème pour exécuter des tests de manière sélective (Exemple: @group only sur les méthodes de test et phpunit --group only)

Ensuite, réduisez le délai d'attente de verrouillage (SET GLOBAL innodb_lock_wait_timeout = 10). De cette façon, vous obtenez un retour rapide et ne passez pas votre journée entière à attendre l'exécution des tests. Le kilométrage peut varier. Adaptez-vous à vos conditions spécifiques.

Troisièmement, recherchez les transactions non fermées, c'est-à-dire, commencez sans annulation ni validation. Cela s'est avéré être exactement ce que mon problème était. Mon try/catch n'était pas assez enveloppant de la logique et il y avait une erreur entre begin transaction et try-catch-rollback.

Quatrièmement, envisagez de placer toutes les parties de la transaction dans le même try-catch, ce qui présente certains avantages de garantir que toutes les parties sont là et facilement visibles. Exemple:

    try {
        DB::beginTransaction();
        $this->someMethodThatMightThrow();
        DB::commit();
    } catch (Exception $e) {
        DB::rollBack();
        throw $e;
    }

C'est mes deux centimes. Si tout va bien utile à quelqu'un sur Internet.

3
Stoutie

Ce problème est lié à la base de données mysql. J'avais fait face au même et en suivant les étapes résolues avec succès. 

Recherchez le fichier usr/local/var/mysql/votre_nom_ordinateur.local.err et comprenez plus d'informations sur l'erreur

Emplacement: /usr/local/var/mysql/votre_nom_ordinateur.local.err

C'est probablement un problème d'autorisations

  1. Trouvez si mysql est en marche et tuez-le

ps -ef | grep mysql

tuer -9 PID

où PID est la valeur de la deuxième colonne 2. vérifier la propriété de mysql

ls -laF/usr/local/var/mysql /

if it is owned by root, change it mysql or your user name



Sudo chown -R mysql/usr/local/var/mysql /

0
Amitesh