Laravel - 锁定等待超时超过

时间:2016-08-10 07:14:23

标签: php mysql laravel transactions

我的代码中有很多事务,如果在其中一个没有触发提交或回滚的事务中执行时发生错误,则数据库被锁定,并且随后尝试访问数据库结果在这:

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也会停止工作。我该怎么办呢?

5 个答案:

答案 0 :(得分:4)

我看到重复的问题

How to debug Lock wait timeout exceeded on MySQL?

您应该考虑通过设置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

这可能是权限问题

  1. 查找mysql是否正在运行并将其杀死
  2.   

    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;
}