Laravel - превышено время ожидания блокировки

У меня много транзакций в моем коде, и если возникает ошибка при выполнении одной из этих транзакций, которая не вызывает фиксацию или откат, тогда база данных заблокирована, и любые последующие попытки доступа к базе данных приводят к этому

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

В контроллере:

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();

Таким образом, даже миграция php-artisan: refresh или php artisan migrate: reset перестает работать. Как мне это исправить?

Ответ 1

Я вижу повторяющийся вопрос

Как отлаживать время ожидания ожидания ожидания ожидания на сервере MySQL?

Вам следует подумать об увеличении значения ожидания ожидания блокировки для InnoDB, установив innodb_lock_wait_timeout, значение по умолчанию - 50 секунд

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

Вы можете установить его на большее значение в /etc/my.cnf навсегда с помощью этой строки

[mysqld]
innodb_lock_wait_timeout=120

и перезапустите mysql. Если вы не можете перезапустить mysql в это время, запустите это:

SET GLOBAL innodb_lock_wait_timeout = 120`; 

Вы также можете просто установить его на время сеанса

SET innodb_lock_wait_timeout = 120; 

Ответ 2

Вот несколько советов по моему опыту...

Если вы выполняете тестовую разработку, изолируйте, какая комбинация тестов выдает ошибку. Используйте любой механизм, обеспечиваемый вашей экосистемой для выборочного запуска тестов (пример: @group only для методов тестирования и phpunit --group only)

Затем уменьшите время ожидания ожидания блокировки (SET GLOBAL innodb_lock_wait_timeout = 10). Таким образом, вы получаете быструю обратную связь и не тратите весь свой день на ожидание тестов. Пробег может отличаться. Отрегулируйте ваши конкретные условия.

В-третьих, обратите внимание на незакрытые транзакции, т.е. начните без отката или фиксации. Это оказалось именно моей проблемой. Моя попытка/улов не обертывала достаточно логики, и это было ошибкой между началом транзакции и откатом от try-catch.

В-четвертых, рассмотрите возможность размещения всех частей транзакции в одном и том же try-catch, который имеет некоторые преимущества в том, чтобы убедиться, что все части там и легко видны. Пример:

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

Это мои два цента. Надеюсь, полезно кому-то в Интернете.

Ответ 3

Эта проблема связана с базой данных mysql. Я столкнулся с одним и тем же шагом и успешно выполнил следующие шаги.

Найдите файл usr/local/var/mysql/your_computer_name.local.err и узнайте больше информации об ошибке

Местоположение:/usr/local/var/mysql/your_computer_name.local.err

Вероятно, проблема с разрешениями

  • Найти, если mysql запущен и убить его

ps -ef | grep mysql

kill -9 PID

где PID - это второе значение столбца  2. проверить принадлежность 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/

Ответ 4

Перезапуск базы данных исправил эту проблему для меня.