【问题标题】:What happens to a Laravel DB Transaction if an exception is thrown?如果抛出异常,Laravel DB 事务会发生什么?
【发布时间】:2017-04-07 22:00:24
【问题描述】:

我认为*交易被丢弃了。这准确吗?

我正在使用 mysql

例子:

try {
    DB::beginTransaction();
    throw new Exception("something happened");
    DB::commit()
} catch (Exception $e) {
    Log::debug("something bad happened");
}

谢谢

【问题讨论】:

    标签: php mysql laravel laravel-5


    【解决方案1】:

    未提交的事务将在 SQL 中被丢弃。

    当你在这里抛出异常时,DB::commit() 永远不会到达。您将直接进入 catch() 块,因此该事务将被丢弃(只要以后不在某处调用 DB::commit())。

    但是,如果您不想在抛出异常时提交事务,我仍然建议您在 catch 块中显式回滚事务,这将关闭该事务并防止对您未来的查询产生任何影响执行。

    try {
        DB::beginTransaction();
        throw new Exception("something happened");
        DB::commit()
    } catch (Exception $e) {
        Log::debug("something bad happened");
        DB::rollBack();
    }
    

    或者使用带有闭包的内置 DB::transaction() 在未捕获异常时自动回滚,记录在这里:https://laravel.com/docs/5.3/database#database-transactions

    【讨论】:

    • 谢谢。它会保留交易并进行某种清理过程吗?
    • 事务将保持打开状态,直到脚本完成执行,届时,将有一个清理过程关闭/丢弃该事务。因此,我添加了关于在引发异常时显式回滚事务的建议。
    • 如果成功执行,我可以使用 Db::commit 来回显某些内容吗
    【解决方案2】:

    如果你在闭包中使用,比如:

    DB::transaction(function () {
        DB::table('users')->update(['votes' => 1]);
        DB::table('posts')->delete();
    });
    

    您将在框架内运行此代码:

    public function transaction(Closure $callback)
    {
        $this->beginTransaction();
    
        // We'll simply execute the given callback within a try / catch block
        // and if we catch any exception we can rollback the transaction
        // so that none of the changes are persisted to the database.
        try {
            $result = $callback($this);
    
            $this->commit();
        }
    
        // If we catch an exception, we will roll back so nothing gets messed
        // up in the database. Then we'll re-throw the exception so it can
        // be handled how the developer sees fit for their applications.
        catch (Exception $e) {
            $this->rollBack();
    
            throw $e;
        } catch (Throwable $e) {
            $this->rollBack();
    
            throw $e;
        }
    
        return $result;
    }
    

    因此,在这种情况下,您 100% 确定事务将回滚。如果您使用DB::beginTransaction(); 手动打开事务,则无法确定该事务是否会回滚,除非您使用以下内容确定:

    try {
        DB::beginTransaction();
        //do something
        DB::commit();
    } catch (\Exception $e) {
        DB::rollback();
    }
    

    如果你在没有catch的情况下抛出异常,脚本死亡或以打开的事务结束,PDO将自动回滚(http://php.net/manual/en/pdo.transactions.php):

    当脚本结束或连接即将关闭时,如果有未完成的事务,PDO 会自动回滚。

    【讨论】:

      猜你喜欢
      • 2011-02-24
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2011-08-18
      • 2011-09-19
      • 2015-08-20
      • 1970-01-01
      相关资源
      最近更新 更多