我正在运行laravel 5.4
并注意到事务中的回滚不起作用。我将数据库引擎设置为InnoDB
文件中的settings.php
并尝试DB::rollback();
和DB::rollBack();
(即大写和小写b),但它不会回滚我的数据库。< / p>
我在下面写了一个单元测试。它创建一个记录,提交它,然后回滚。但是,最后一个断言失败了。回滚后,仍会在数据库中找到该记录。有什么我想念的吗?或者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(),
]);
}
答案 0 :(得分:1)
交易包括三个步骤:
您使用DB::beginTransaction
或MySQL等效BEGIN TRANSACTION
启动它,然后执行您需要的命令然后(这里是重要的部分) {{1 } 或 COMMIT
但是,一旦你完成了交易,你就不能再回滚了。
将测试更改为:
ROLLBACK
这应该有效,因为在回滚事务之前,数据库“认为”记录在那里。
在使用交易时,您希望使用the docs中建议的内容,例如:
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(),
]);
}
这将确保包装操作的原子性,并且如果在函数体内抛出异常将会回滚(如果需要,您也可以将自己作为中止的手段)。
答案 1 :(得分:1)
提交后无法回滚。我可以看到你使用了提交
DB::commit();
回滚之前
所以你只有在它无法提交时才能回滚。你可以使用try catch block
DB::beginTransaction();
try {
DB::insert(...);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
}
答案 2 :(得分:1)
嗯......你误解了交易是如何运作的。
开始事务后,您可以提交或回滚它。提交意味着到目前为止您在事务期间对数据库所做的所有更改都已完成并且#34; (即永久)在数据库中。一旦你承诺,就没有什么可以回滚。
如果要回滚,则必须在提交之前执行此操作。回滚将使数据库进入您开始交易之前的状态。
这意味着您有两个选择:
1)开始一个事务,然后提交到目前为止所做的所有更改。
2)开始一个事务,然后回滚到目前为止所做的所有更改。
提交和回滚都是事务的最终操作,即结束事务。提交或回滚后,交易将从数据库的角度完成。
您还可以通过以下方式查看此内容:
通过启动事务,您告诉数据库所有后续更改都是初步/临时更改。完成更改后,您可以告诉数据库永久更改这些更改(通过提交),或者告诉数据库丢弃(还原)更改(通过回滚)。
回滚后,更改将丢失,因此无法再次提交。提交后,更改是永久性的,因此无法回滚。只要更改处于临时状态,就可以进行提交和回滚。