如果抛出异常,Laravel DB 事务会发生什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40772160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 14:48:10  来源:igfitidea点击:

What happens to a Laravel DB Transaction if an exception is thrown?

phpmysqllaravellaravel-5

提问by timbroder

I think* the transaction is just discarded. Is this accurate?

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

I'm using mysql

我正在使用 mysql

Example:

例子:

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

Thanks

谢谢

采纳答案by Devon

A transaction that isn't committed will be discarded in SQL.

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

When you throw the exception here, DB::commit()is never reached. You'll go straight to the catch() block and therefore the transaction will be discarded (as long as DB::commit()isn't called somewhere later).

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

However, I would still always recommend explicitly rolling back the transaction in your catch block if you do not want to commit the transaction when an exception is thrown, this will close out that transaction and prevent any effect on your future queries in that execution.

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

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

Or use the built in DB::transaction() with a closure to automatically rollback when an exception is uncaught, documented here: https://laravel.com/docs/5.3/database#database-transactions

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

回答by Felippe Duarte

If you are using in a Closure, like:

如果您在闭包中使用,例如:

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

You'll run this code inside framework:

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

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

So, in this case, you are 100% sure that the transaction is going to rollback. If you open manually transaction with DB::beginTransaction();, there is no way to be sure that is going to rollback, unless you make sure with something like:

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

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

If you throw an exception without catch, the scripts die or end with opened transaction, PDO will automatically rollback (http://php.net/manual/en/pdo.transactions.php):

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

When the script ends or when a connection is about to be closed, if you have an outstanding transaction, PDO will automatically roll it back.

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