具有多个提交的Laravel DB事务?

时间:2017-03-14 09:59:31

标签: php mysql laravel transactions

我可以在数据库事务期间制作一些检查点吗?

例如,当事务开始时,我有许多查询,更新,删除等。

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

据我了解,如果出现问题,这种函数会自动提交所有内容以及回滚。

但是如果出现错误,是否有可能不回滚所有内容,例如

DB::table('users')->update(['votes' => 1]);
// something else here
DB::if_successful_so_far_do_not_rollback_previous_lines();
DB::table('posts')->delete();

是否存在“小内部提交”?

1 个答案:

答案 0 :(得分:3)

是的,你可以。但这也取决于您使用的数据库。

Laravel支持嵌套事务。这与你需要的东西很接近。

要隔离内部事务,必须将其包装在try-catch块中。因此,如果内部事务抛出异常,它将不会到达外部事务,因此继续该过程。但是如果外部事务抛出异常,整个事务(包括其嵌套事务)将回滚。

所以你最终会得到这样的东西:

public function testNestedTransactions()
{

    $user = EloquentTestUser::create(['email' => 'taylor@laravel.com']);

    $this->connection()->transaction(function () use ($user) {

        try {
            $this->connection()->transaction(function () use ($user) {
                $user->email = 'otwell@laravel.com';
                $user->save();
                throw new Exception;
            });
        } catch (Exception $e) {}

        $user = EloquentTestUser::first();
        $this->assertEquals('taylor@laravel.com', $user->email);

    });

}

这是Otwell在this commit implementing the functionality of nested transactions in Laravel写的测试。他首先创建一个用户,然后使用嵌套事务启动一个事务,在那里他更新用户电子邮件,然后抛出一个异常(意味着发生了错误)。在它的正下方,他检查用户的电子邮件在创建时是否仍然保持不变,并且确实如此,因为嵌套事务已经回滚,但外部事务仍然存在。