如果在laravel5中调用DB::beginTransaction而没有调用DB::commit()会发生什么?

3
通常情况下,使用DB::beginTransaction()时,会与DB::rollBack()一起使用。
就像这样:
DB::beginTrnsaction();
try {
    DB::insert(...);
    DB::insert(...);
    DB::insert(...);

    DB::commit();
    // all good
} catch (\Exception $e) {
    DB::rollback();
    // something went wrong
}

然而,如果我忘记添加try catch循环呢?

例如:

DB::beginTrnsaction();
DB::insert(...);
DB::insert(...);
DB::insert(...);
DB::commit();

如果插入操作失败,数据库会被更改吗?还是会自动回滚?


3
如果任何一个插入查询出现错误,事务将自动回滚。 - Rohit shah
是的,它会自动回滚。 - Anowar Hossain
1
这个你可以通过创建一个测试用例来自行测试。 - Jeroen Heier
1
@JeroenHeier 太对了。太重要了。学会测试,忘掉其它。 - Ohgodwhy
我知道我可以自己测试,但我想知道它是否会自动回滚,为什么其他人建议使用try catch循环? - cytsunny
2个回答

2
如果您启动了一个事务,但从未提交或回滚,当与数据库的连接关闭时,事务将自动回滚。
对于大多数PHP页面来说,这并不是什么大问题,因为连接通常在请求完成后关闭。
然而,如果您使用持久连接,这就成为了一个问题。使用持久连接时,当请求完成后,与数据库的连接并没有结束。连接会回到连接池中,保持活动状态,并且事务仍然处于打开状态。事务仍然处于打开状态时,记录上的锁定仍然有效,这可能会阻止随后的请求访问这些记录,直到连接被终止且错误事务可以回滚。
就事务而言,它们越短暂越好。您希望事务保持活动状态足够长的时间来完成您的工作单元,但您不希望它保持活动状态的时间超过那个时间。尽快提交或回滚以完成事务,其他进程等待获取记录锁的时间就越短。这可能会严重影响高负载站点。
您可以做的一件事是在传递给transaction()方法的Closure中执行您的工作。这将自动处理事务的开始和提交/回滚。
DB::transaction(function () {
    DB::insert(...);
    DB::insert(...);
    DB::insert(...);
});

如果在Closure内部抛出任何异常,则事务将被回滚。否则,事务将提交。


1
我的交易涉及许多变量,使用闭包不方便,因为我需要在 use()global 中复制变量列表。在我的情况下,我更喜欢使用 try catch 方法。 - cytsunny
@cytsunny 在数组中分配变量并使用use($your_array)该数组... - Kyslik
有必要在try catch解决问题时分配变量吗? - cytsunny

0

尝试理解概念:

BEGIN TRANSACTION -> 从数据库的最后一致状态开始

你的代码

if($condition)
{
    // ROLLBACK
}
else
{
    // COMMIT
}

回滚意味着撤销您所做的所有更改,并从最后一个一致状态开始。

提交意味着一切正常,您希望保存更改以使其持久化。

注意:如果您不提交,则所有更改都将被丢弃。


我明白它们的作用……只是我想知道,如果它会自动回滚,为什么那些人建议使用try catch循环? - cytsunny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接