2017-03-14 31 views
2

DBトランザクション中にいくつかのチェックポイントを作成できますか?複数のコミットを持つLaravel DBトランザクション?

たとえば、トランザクションが開始されると、多くのクエリ、更新、削除などが発生します。何かがうまくいかない場合

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

のように任意の「小さな内側のコミット」が存在しますか?

+2

2つのコミットで分割してください。 :) – manniL

+0

私はできるだけ少数の接続を使用しようとしています – Coffee

+0

まあ、私はそれが唯一の解決策だと思います。私はあなたがトランザクションを「部分的にロールバック」できるとは思わない。 – manniL

答えて

2

はい、できます。しかし、これはまたあなたが使用しているデータベースによって異なります。

Laravelはネストされたトランザクションをサポートします。あなたが必要とするものに近いものです。

内部トランザクションを分離するには、内部トランザクションをtry-catchブロック内にラップする必要があります。したがって、内部トランザクションが例外をスローした場合、外部トランザクションには到達しないため、プロセスが継続されます。しかし、外部トランザクションが例外をスローすると、そのトランザクション全体(ネストされたトランザクションを含む)がロールバックされます。

ですから、このようなものになってしまいます。

public function testNestedTransactions() 
{ 

    $user = EloquentTestUser::create(['email' => '[email protected]']); 

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

     try { 
      $this->connection()->transaction(function() use ($user) { 
       $user->email = '[email protected]'; 
       $user->save(); 
       throw new Exception; 
      }); 
     } catch (Exception $e) {} 

     $user = EloquentTestUser::first(); 
     $this->assertEquals('[email protected]', $user->email); 

    }); 

} 

これはthis commit implementing the functionality of nested transactions in LaravelにOtwellによって書かれたテストです。まずユーザーを作成し、ネストされたトランザクションを使用してトランザクションを開始し、ユーザーの電子メールを更新して例外をスローします(エラーが発生したことを意味します)。そのすぐ下に、ユーザーの電子メールが作成時に同じままであるかどうかをチェックします。ネストされたトランザクションはロールバックされていますが、外側のトランザクションはまだ進行中です。

関連する問題