具有多次提交的 Laravel 数据库事务?

Cof*_*fee 4 php mysql transactions laravel

我可以在 DB 事务期间做一些检查点吗?

比如事务开始的时候,我有很多查询、更新、删除等等。

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

据我了解,这种功能会在成功的情况下自动提交所有内容,如果出现问题则回滚。

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

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

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

Art*_*ira 7

Yes, you can. But this also depends on the database you are using.

Laravel supports nested transactions. Which is something close to what you need.

To isolate an inner transaction, you have to wrap it inside a try-catch block. So if the inner transaction throws an exception, it will not reach the outer transaction, therefore continuing the process. But if the outer transaction throws an Exception, the whole transaction (including its nested transactions) will roll back.

So you will end up with something like this:

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

    });

}
Run Code Online (Sandbox Code Playgroud)

This is a test written by Otwell in this commit implementing the functionality of nested transactions in Laravel. He first create an user, then start a transaction with a nested transaction where he updates the user email and then throws an exception (meaning an error has ocurred). Right under it, he checks if the user email stills the same when he created it, and it does, because the nested transaction has rolled back, but the outer transaction stills going.