我的代码中有很多事务,如果在其中一个没有触发提交或回滚的事务中执行时发生错误,则数据库被锁定,并且随后尝试访问数据库结果在这:
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工匠迁移:刷新或php artisan migrate:reset也会停止工作。我该怎么办呢?
答案 0 :(得分:4)
我看到重复的问题
您应该考虑通过设置innodb_lock_wait_timeout来增加InnoDB的锁定等待超时值,默认为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;
答案 1 :(得分:3)
以下是我的经验中的一些提示......
如果您正在进行测试驱动开发,请确定哪种测试组合会产生错误。利用您的生态系统提供的任何机制来有选择地运行测试(例如:@group only
关于测试方法和phpunit --group only
)
接下来,减少锁定等待超时(SET GLOBAL innodb_lock_wait_timeout = 10
)。这样您就可以获得快速反馈,而不是花一整天等待测试运行。里程可能会有所不同。根据您的具体情况进行调整。
第三,寻找未结算的交易,即在没有回滚或提交的情况下开始。事实证明这正是我的问题所在。我的try / catch没有包含足够的逻辑,并且在begin transaction和try-catch-rollback之间出错。
第四,考虑将交易的所有部分放在同一个try-catch中,这样可以确保所有部件都在那里并且很容易看到。例如:
try {
DB::beginTransaction();
$this->someMethodThatMightThrow();
DB::commit();
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
那是我的两分钱。希望对互联网上的某些人有用。
答案 2 :(得分:0)
此问题与mysql数据库有关。我面对同样的事情,通过以下步骤成功地解决了它。
查找usr / local / var / mysql / your_computer_name.local.err文件并了解有关错误的更多信息
位置:/usr/local/var/mysql/your_computer_name.local.err
这可能是权限问题
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 /
答案 3 :(得分:0)
重新启动数据库为我解决了此问题。
答案 4 :(得分:0)
很可能您的异常没有被捕获,因为它不是异常而是致命错误或其他类型的 \Throwable
。
您可以将 DB::transaction
方法与回调一起使用,这是一种更安全的替代方法,因为它会为您处理所有这些并且几乎等同于您的代码(除了它还捕获 \Throwable
)>
DB::transaction(function () {
$this->someMethodThatMightThrow();
});
或者确保你用
DB::beginTransaction();
try {
//..
DB::commit();
} catch (\Throwable $e) {
DB::rollback();
throw $e;
}