2017-10-07 102 views
0

我正在运行laravel 5.4并注意到事务回滚不起作用。我在settings.php文件中将我的数据库引擎设置为InnoDB,并尝试DB::rollback();DB::rollBack();(即大写和小写b),但它不回滚我的数据库。Laravel事务回滚似乎不起作用

我写了一个单元测试波纹管。它创建一个记录,提交它,然后回滚。然而,最后的断言失败了。在回滚之后,数据库中仍然存在该记录。有什么我失踪?或者是否有laravel的错误?

public function testRollback() 
{ 
    $this->artisan('migrate:refresh', [ 
     '--seed' => '1' 
    ]); 

    DB::beginTransaction(); 

    Season::create(['start_date' => Carbon::now(), 'end_date' => Carbon::now(),]); 
    DB::commit(); 
    $this->assertDatabaseHas('seasons', [ 
     'start_date' => Carbon::now(), 'end_date' => Carbon::now(), 
    ]); 

    DB::rollBack(); 
    // This assertion fails. It still finds the record after calling roll back 
    $this->assertDatabaseMissing('seasons', [ 
     'start_date' => Carbon::now(), 'end_date' => Carbon::now(), 
    ]); 
} 

回答

1

本次交易包括三个步骤:

您与DB::beginTransaction或MySQL等同BEGIN TRANSACTION,那么你执行你需要,然后命令(在这里是最重要的部分),你要么COMMIT启动ROLLBACK

但是,一旦你承诺交易完成了,你不能再回滚了。

更改测试:

public function testRollback() 
{ 
    $this->artisan('migrate:refresh', [ 
     '--seed' => '1' 
    ]); 

    DB::beginTransaction(); 

    Season::create(['start_date' => Carbon::now(), 'end_date' => Carbon::now(),]); 

    $this->assertDatabaseHas('seasons', [ 
     'start_date' => Carbon::now(), 'end_date' => Carbon::now(), 
    ]); 

    DB::rollback(); 

    $this->assertDatabaseMissing('seasons', [ 
     'start_date' => Carbon::now(), 'end_date' => Carbon::now(), 
    ]); 
} 

这应该是因为工作,直到事务回滚数据库“认为”的纪录就在那里。

在实践中使用你想用什么在the docs建议交易时,例如:

DB::transaction(function() 
{ 
    DB::table('users')->update(array('votes' => 1)); 

    DB::table('posts')->delete(); 
}); 

这将确保包装操作的原子,如果有异常的函数体中抛出将回滚(你如果需要的话,也可以将自己作为中止的手段)。

1

不能回滚一旦你commit.As我可以看到你已经使用提交

DB::commit(); 

回滚之前

所以你只能回滚时,它会未能提交。你可以使用try catch块

DB::beginTransaction(); 
    try { 
     DB::insert(...); 
     DB::commit(); 
    } catch (\Exception $e) { 
     DB::rollback(); 

    } 
1

Emmm ...你误会了事务是如何工作的。

开始事务后,您可以提交它或回滚它。承诺意味着在到目前为止的事务处理中对数据库所做的所有更改都将在数据库中“最终确定”(即永久化)。只要你承诺,没有什么可以回滚的。

如果你想回滚,你必须这样做之前你提交的。回滚将使数据库进入开始交易之前的状态。

这意味着你到底有两种选择:

1)开始事务,然后提交到目前为止所做的所有更改。

2)开始一个事务,然后回滚到目前为止所做的所有更改。

对于交易,即结束交易,提交和回滚均为最终动作。当提交或回滚时,交易从数据库的角度完成。

你也可以看看这个以下列方式:

通过启动交易时,你是在告诉所有的以下变化是初步/临时数据库。完成更改后,您可以告诉数据库使这些更改永久(通过提交),或者告诉数据库丢弃(回退)更改(通过回滚)。

回滚后,更改将丢失,因此无法再次提交。在您提交之后,这些更改是永久的,因此无法回滚。只有在更改处于临时状态时,才可以进行提交和回滚。