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

时间:2016-11-23 18:51:10

标签: php mysql laravel laravel-5

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

我正在使用mysql

示例:

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

由于

2 个答案:

答案 0 :(得分:5)

如果你在Closure中使用,例如:

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将自动回滚。

答案 1 :(得分:3)

未提交的事务将在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