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
Я вижу повторяющийся вопрос
Вам следует подумать об увеличении значения ожидания ожидания блокировки для 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
Перезапуск базы данных исправил эту проблему для меня.